root/source3/utils/net_rpc.c

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

DEFINITIONS

This source file includes following definitions.
  1. net_get_remote_domain_sid
  2. run_rpc_command
  3. rpc_changetrustpw_internals
  4. net_rpc_changetrustpw
  5. rpc_oldjoin_internals
  6. net_rpc_perform_oldjoin
  7. net_rpc_oldjoin
  8. net_rpc_join
  9. rpc_info_internals
  10. net_rpc_info
  11. rpc_getsid_internals
  12. net_rpc_getsid
  13. rpc_user_usage
  14. rpc_user_add
  15. rpc_user_rename
  16. rpc_user_delete
  17. rpc_user_password
  18. rpc_user_info
  19. rpc_user_list
  20. net_rpc_user
  21. rpc_sh_user_list
  22. rpc_sh_user_info
  23. rpc_sh_handle_user
  24. rpc_sh_user_show_internals
  25. rpc_sh_user_show
  26. rpc_sh_user_str_edit_internals
  27. rpc_sh_user_str_edit
  28. rpc_sh_user_flag_edit_internals
  29. rpc_sh_user_flag_edit
  30. net_rpc_user_edit_cmds
  31. net_rpc_user_cmds
  32. rpc_group_usage
  33. rpc_group_delete_internals
  34. rpc_group_delete
  35. rpc_group_add_internals
  36. rpc_alias_add_internals
  37. rpc_group_add
  38. get_sid_from_name
  39. rpc_add_groupmem
  40. rpc_add_aliasmem
  41. rpc_group_addmem_internals
  42. rpc_group_addmem
  43. rpc_del_groupmem
  44. rpc_del_aliasmem
  45. rpc_group_delmem_internals
  46. rpc_group_delmem
  47. rpc_group_list_internals
  48. rpc_group_list
  49. rpc_list_group_members
  50. rpc_list_alias_members
  51. rpc_group_members_internals
  52. rpc_group_members
  53. rpc_group_rename_internals
  54. rpc_group_rename
  55. net_rpc_group
  56. rpc_share_usage
  57. rpc_share_add
  58. rpc_share_delete
  59. display_share_info_1
  60. get_share_info
  61. rpc_share_list
  62. check_share_availability
  63. check_share_sanity
  64. rpc_share_migrate_shares_internals
  65. rpc_share_migrate_shares
  66. copy_fn
  67. sync_files
  68. copy_top_level_perms
  69. rpc_share_migrate_files_internals
  70. rpc_share_migrate_files
  71. rpc_share_migrate_security_internals
  72. rpc_share_migrate_security
  73. rpc_share_migrate_all
  74. rpc_share_migrate
  75. push_alias
  76. rpc_fetch_domain_aliases
  77. rpc_aliaslist_dump
  78. rpc_aliaslist_internals
  79. init_user_token
  80. free_user_token
  81. add_sid_to_token
  82. dump_user_token
  83. is_alias_member
  84. collect_sid_memberships
  85. collect_alias_memberships
  86. get_user_sids
  87. get_user_tokens
  88. get_user_tokens_from_file
  89. show_userlist
  90. collect_share
  91. rpc_share_allowedusers_internals
  92. rpc_share_allowedusers
  93. net_usersidlist
  94. net_usersidlist_usage
  95. net_rpc_share
  96. rpc_sh_share_list
  97. rpc_sh_share_add
  98. rpc_sh_share_delete
  99. rpc_sh_share_info
  100. net_rpc_share_cmds
  101. rpc_file_usage
  102. rpc_file_close
  103. display_file_info_3
  104. rpc_file_user
  105. net_rpc_file
  106. rpc_shutdown_abort_internals
  107. rpc_reg_shutdown_abort_internals
  108. rpc_shutdown_abort
  109. rpc_init_shutdown_internals
  110. rpc_reg_shutdown_internals
  111. rpc_shutdown
  112. rpc_trustdom_add_internals
  113. rpc_trustdom_add
  114. rpc_trustdom_del_internals
  115. rpc_trustdom_del
  116. rpc_trustdom_get_pdc
  117. rpc_trustdom_establish
  118. rpc_trustdom_revoke
  119. rpc_query_domain_sid
  120. print_trusted_domain
  121. vampire_trusted_domain
  122. rpc_trustdom_vampire
  123. rpc_trustdom_list
  124. rpc_trustdom
  125. net_rpc_check
  126. rpc_samdump
  127. rpc_vampire
  128. rpc_printer_migrate_all
  129. rpc_printer_migrate_drivers
  130. rpc_printer_migrate_forms
  131. rpc_printer_migrate_printers
  132. rpc_printer_migrate_security
  133. rpc_printer_migrate_settings
  134. rpc_printer_migrate
  135. rpc_printer_list
  136. rpc_printer_driver_list
  137. rpc_printer_publish_publish
  138. rpc_printer_publish_update
  139. rpc_printer_publish_unpublish
  140. rpc_printer_publish_list
  141. rpc_printer_publish
  142. rpc_printer_usage
  143. net_rpc_printer
  144. net_rpc

   1 /*
   2    Samba Unix/Linux SMB client library
   3    Distributed SMB/CIFS Server Management Utility
   4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
   5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
   6    Copyright (C) 2004,2008 Guenther Deschner (gd@samba.org)
   7    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
   8    Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
   9 
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14 
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19 
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
  22 
  23 #include "includes.h"
  24 #include "utils/net.h"
  25 
  26 static int net_mode_share;
  27 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
  28 
  29 /**
  30  * @file net_rpc.c
  31  *
  32  * @brief RPC based subcommands for the 'net' utility.
  33  *
  34  * This file should contain much of the functionality that used to
  35  * be found in rpcclient, execpt that the commands should change
  36  * less often, and the fucntionality should be sane (the user is not
  37  * expected to know a rid/sid before they conduct an operation etc.)
  38  *
  39  * @todo Perhaps eventually these should be split out into a number
  40  * of files, as this could get quite big.
  41  **/
  42 
  43 
  44 /**
  45  * Many of the RPC functions need the domain sid.  This function gets
  46  *  it at the start of every run
  47  *
  48  * @param cli A cli_state already connected to the remote machine
  49  *
  50  * @return The Domain SID of the remote machine.
  51  **/
  52 
  53 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  54                                    DOM_SID **domain_sid,
  55                                    const char **domain_name)
  56 {
  57         struct rpc_pipe_client *lsa_pipe = NULL;
  58         struct policy_handle pol;
  59         NTSTATUS result = NT_STATUS_OK;
  60         union lsa_PolicyInformation *info = NULL;
  61 
  62         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
  63                                           &lsa_pipe);
  64         if (!NT_STATUS_IS_OK(result)) {
  65                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
  66                 return result;
  67         }
  68 
  69         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
  70                                      SEC_FLAG_MAXIMUM_ALLOWED,
  71                                      &pol);
  72         if (!NT_STATUS_IS_OK(result)) {
  73                 d_fprintf(stderr, "open_policy failed: %s\n",
  74                           nt_errstr(result));
  75                 return result;
  76         }
  77 
  78         result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
  79                                             &pol,
  80                                             LSA_POLICY_INFO_ACCOUNT_DOMAIN,
  81                                             &info);
  82         if (!NT_STATUS_IS_OK(result)) {
  83                 d_fprintf(stderr, "lsaquery failed: %s\n",
  84                           nt_errstr(result));
  85                 return result;
  86         }
  87 
  88         *domain_name = info->account_domain.name.string;
  89         *domain_sid = info->account_domain.sid;
  90 
  91         rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
  92         TALLOC_FREE(lsa_pipe);
  93 
  94         return NT_STATUS_OK;
  95 }
  96 
  97 /**
  98  * Run a single RPC command, from start to finish.
  99  *
 100  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
 101  * @param conn_flag a NET_FLAG_ combination.  Passed to
 102  *                   net_make_ipc_connection.
 103  * @param argc  Standard main() style argc.
 104  * @param argv  Standard main() style argv. Initial components are already
 105  *              stripped.
 106  * @return A shell status integer (0 for success).
 107  */
 108 
 109 int run_rpc_command(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 110                         struct cli_state *cli_arg,
 111                         const struct ndr_syntax_id *interface,
 112                         int conn_flags,
 113                         rpc_command_fn fn,
 114                         int argc,
 115                         const char **argv)
 116 {
 117         struct cli_state *cli = NULL;
 118         struct rpc_pipe_client *pipe_hnd = NULL;
 119         TALLOC_CTX *mem_ctx;
 120         NTSTATUS nt_status;
 121         DOM_SID *domain_sid;
 122         const char *domain_name;
 123         int ret = -1;
 124 
 125         /* make use of cli_state handed over as an argument, if possible */
 126         if (!cli_arg) {
 127                 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
 128                 if (!NT_STATUS_IS_OK(nt_status)) {
 129                         DEBUG(1, ("failed to make ipc connection: %s\n",
 130                                   nt_errstr(nt_status)));
 131                         return -1;
 132                 }
 133         } else {
 134                 cli = cli_arg;
 135         }
 136 
 137         if (!cli) {
 138                 return -1;
 139         }
 140 
 141         /* Create mem_ctx */
 142 
 143         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
 144                 DEBUG(0, ("talloc_init() failed\n"));
 145                 goto fail;
 146         }
 147 
 148         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
 149                                               &domain_name);
 150         if (!NT_STATUS_IS_OK(nt_status)) {
 151                 goto fail;
 152         }
 153 
 154         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
 155                 if (lp_client_schannel()
 156                     && (ndr_syntax_id_equal(interface,
 157                                             &ndr_table_netlogon.syntax_id))) {
 158                         /* Always try and create an schannel netlogon pipe. */
 159                         nt_status = cli_rpc_pipe_open_schannel(
 160                                 cli, interface, NCACN_NP,
 161                                 PIPE_AUTH_LEVEL_PRIVACY, domain_name,
 162                                 &pipe_hnd);
 163                         if (!NT_STATUS_IS_OK(nt_status)) {
 164                                 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
 165                                         nt_errstr(nt_status) ));
 166                                 goto fail;
 167                         }
 168                 } else {
 169                         if (conn_flags & NET_FLAGS_SEAL) {
 170                                 nt_status = cli_rpc_pipe_open_ntlmssp(
 171                                         cli, interface,
 172                                         (conn_flags & NET_FLAGS_TCP) ?
 173                                         NCACN_IP_TCP : NCACN_NP,
 174                                         PIPE_AUTH_LEVEL_PRIVACY,
 175                                         lp_workgroup(), c->opt_user_name,
 176                                         c->opt_password, &pipe_hnd);
 177                         } else {
 178                                 nt_status = cli_rpc_pipe_open_noauth(
 179                                         cli, interface,
 180                                         &pipe_hnd);
 181                         }
 182                         if (!NT_STATUS_IS_OK(nt_status)) {
 183                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
 184                                         get_pipe_name_from_iface(interface),
 185                                         nt_errstr(nt_status) ));
 186                                 goto fail;
 187                         }
 188                 }
 189         }
 190 
 191         nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
 192 
 193         if (!NT_STATUS_IS_OK(nt_status)) {
 194                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
 195         } else {
 196                 ret = 0;
 197                 DEBUG(5, ("rpc command function succedded\n"));
 198         }
 199 
 200         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
 201                 if (pipe_hnd) {
 202                         TALLOC_FREE(pipe_hnd);
 203                 }
 204         }
 205 
 206 fail:
 207         /* close the connection only if it was opened here */
 208         if (!cli_arg) {
 209                 cli_shutdown(cli);
 210         }
 211 
 212         talloc_destroy(mem_ctx);
 213         return ret;
 214 }
 215 
 216 /**
 217  * Force a change of the trust acccount password.
 218  *
 219  * All parameters are provided by the run_rpc_command function, except for
 220  * argc, argv which are passed through.
 221  *
 222  * @param domain_sid The domain sid acquired from the remote server.
 223  * @param cli A cli_state connected to the server.
 224  * @param mem_ctx Talloc context, destroyed on completion of the function.
 225  * @param argc  Standard main() style argc.
 226  * @param argv  Standard main() style argv. Initial components are already
 227  *              stripped.
 228  *
 229  * @return Normal NTSTATUS return.
 230  **/
 231 
 232 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 233                                         const DOM_SID *domain_sid,
 234                                         const char *domain_name,
 235                                         struct cli_state *cli,
 236                                         struct rpc_pipe_client *pipe_hnd,
 237                                         TALLOC_CTX *mem_ctx,
 238                                         int argc,
 239                                         const char **argv)
 240 {
 241 
 242         return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
 243 }
 244 
 245 /**
 246  * Force a change of the trust acccount password.
 247  *
 248  * @param argc  Standard main() style argc.
 249  * @param argv  Standard main() style argv. Initial components are already
 250  *              stripped.
 251  *
 252  * @return A shell status integer (0 for success).
 253  **/
 254 
 255 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 256 {
 257         if (c->display_usage) {
 258                 d_printf("Usage:\n"
 259                          "net rpc changetrustpw\n"
 260                          "    Change the machine trust password\n");
 261                 return 0;
 262         }
 263 
 264         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
 265                                NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
 266                                rpc_changetrustpw_internals,
 267                                argc, argv);
 268 }
 269 
 270 /**
 271  * Join a domain, the old way.
 272  *
 273  * This uses 'machinename' as the inital password, and changes it.
 274  *
 275  * The password should be created with 'server manager' or equiv first.
 276  *
 277  * All parameters are provided by the run_rpc_command function, except for
 278  * argc, argv which are passed through.
 279  *
 280  * @param domain_sid The domain sid acquired from the remote server.
 281  * @param cli A cli_state connected to the server.
 282  * @param mem_ctx Talloc context, destroyed on completion of the function.
 283  * @param argc  Standard main() style argc.
 284  * @param argv  Standard main() style argv. Initial components are already
 285  *              stripped.
 286  *
 287  * @return Normal NTSTATUS return.
 288  **/
 289 
 290 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 291                                         const DOM_SID *domain_sid,
 292                                         const char *domain_name,
 293                                         struct cli_state *cli,
 294                                         struct rpc_pipe_client *pipe_hnd,
 295                                         TALLOC_CTX *mem_ctx,
 296                                         int argc,
 297                                         const char **argv)
 298 {
 299 
 300         fstring trust_passwd;
 301         unsigned char orig_trust_passwd_hash[16];
 302         NTSTATUS result;
 303         uint32 sec_channel_type;
 304 
 305         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
 306                                           &pipe_hnd);
 307         if (!NT_STATUS_IS_OK(result)) {
 308                 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
 309                         "error was %s\n",
 310                         cli->desthost,
 311                         nt_errstr(result) ));
 312                 return result;
 313         }
 314 
 315         /*
 316            check what type of join - if the user want's to join as
 317            a BDC, the server must agree that we are a BDC.
 318         */
 319         if (argc >= 0) {
 320                 sec_channel_type = get_sec_channel_type(argv[0]);
 321         } else {
 322                 sec_channel_type = get_sec_channel_type(NULL);
 323         }
 324 
 325         fstrcpy(trust_passwd, global_myname());
 326         strlower_m(trust_passwd);
 327 
 328         /*
 329          * Machine names can be 15 characters, but the max length on
 330          * a password is 14.  --jerry
 331          */
 332 
 333         trust_passwd[14] = '\0';
 334 
 335         E_md4hash(trust_passwd, orig_trust_passwd_hash);
 336 
 337         result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
 338                                               orig_trust_passwd_hash,
 339                                               sec_channel_type);
 340 
 341         if (NT_STATUS_IS_OK(result))
 342                 printf("Joined domain %s.\n", c->opt_target_workgroup);
 343 
 344 
 345         if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
 346                 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
 347                 result = NT_STATUS_UNSUCCESSFUL;
 348         }
 349 
 350         return result;
 351 }
 352 
 353 /**
 354  * Join a domain, the old way.
 355  *
 356  * @param argc  Standard main() style argc.
 357  * @param argv  Standard main() style argv. Initial components are already
 358  *              stripped.
 359  *
 360  * @return A shell status integer (0 for success).
 361  **/
 362 
 363 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 364 {
 365         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
 366                                NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
 367                                rpc_oldjoin_internals,
 368                                argc, argv);
 369 }
 370 
 371 /**
 372  * Join a domain, the old way.  This function exists to allow
 373  * the message to be displayed when oldjoin was explicitly
 374  * requested, but not when it was implied by "net rpc join".
 375  *
 376  * @param argc  Standard main() style argc.
 377  * @param argv  Standard main() style argv. Initial components are already
 378  *              stripped.
 379  *
 380  * @return A shell status integer (0 for success).
 381  **/
 382 
 383 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 384 {
 385         int rc = -1;
 386 
 387         if (c->display_usage) {
 388                 d_printf("Usage:\n"
 389                          "net rpc oldjoin\n"
 390                          "    Join a domain the old way\n");
 391                 return 0;
 392         }
 393 
 394         rc = net_rpc_perform_oldjoin(c, argc, argv);
 395 
 396         if (rc) {
 397                 d_fprintf(stderr, "Failed to join domain\n");
 398         }
 399 
 400         return rc;
 401 }
 402 
 403 /**
 404  * 'net rpc join' entrypoint.
 405  * @param argc  Standard main() style argc.
 406  * @param argv  Standard main() style argv. Initial components are already
 407  *              stripped
 408  *
 409  * Main 'net_rpc_join()' (where the admin username/password is used) is
 410  * in net_rpc_join.c.
 411  * Try to just change the password, but if that doesn't work, use/prompt
 412  * for a username/password.
 413  **/
 414 
 415 int net_rpc_join(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 416 {
 417         if (c->display_usage) {
 418                 d_printf("Usage:\n"
 419                          "net rpc join -U <username>[%%password] <type>\n"
 420                          "  Join a domain\n"
 421                          "    username\tName of the admin user"
 422                          "    password\tPassword of the admin user, will "
 423                          "prompt if not specified\n"
 424                          "    type\tCan be one of the following:\n"
 425                          "\t\tMEMBER\tJoin as member server (default)\n"
 426                          "\t\tBDC\tJoin as BDC\n"
 427                          "\t\tPDC\tJoin as PDC\n");
 428                 return 0;
 429         }
 430 
 431         if (lp_server_role() == ROLE_STANDALONE) {
 432                 d_printf("cannot join as standalone machine\n");
 433                 return -1;
 434         }
 435 
 436         if (strlen(global_myname()) > 15) {
 437                 d_printf("Our netbios name can be at most 15 chars long, "
 438                          "\"%s\" is %u chars long\n",
 439                          global_myname(), (unsigned int)strlen(global_myname()));
 440                 return -1;
 441         }
 442 
 443         if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
 444                 return 0;
 445 
 446         return net_rpc_join_newstyle(c, argc, argv);
 447 }
 448 
 449 /**
 450  * display info about a rpc domain
 451  *
 452  * All parameters are provided by the run_rpc_command function, except for
 453  * argc, argv which are passed through.
 454  *
 455  * @param domain_sid The domain sid acquired from the remote server
 456  * @param cli A cli_state connected to the server.
 457  * @param mem_ctx Talloc context, destroyed on completion of the function.
 458  * @param argc  Standard main() style argc.
 459  * @param argv  Standard main() style argv. Initial components are already
 460  *              stripped.
 461  *
 462  * @return Normal NTSTATUS return.
 463  **/
 464 
 465 NTSTATUS rpc_info_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 466                         const DOM_SID *domain_sid,
 467                         const char *domain_name,
 468                         struct cli_state *cli,
 469                         struct rpc_pipe_client *pipe_hnd,
 470                         TALLOC_CTX *mem_ctx,
 471                         int argc,
 472                         const char **argv)
 473 {
 474         struct policy_handle connect_pol, domain_pol;
 475         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 476         union samr_DomainInfo *info = NULL;
 477         fstring sid_str;
 478 
 479         sid_to_fstring(sid_str, domain_sid);
 480 
 481         /* Get sam policy handle */
 482         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
 483                                       pipe_hnd->desthost,
 484                                       MAXIMUM_ALLOWED_ACCESS,
 485                                       &connect_pol);
 486         if (!NT_STATUS_IS_OK(result)) {
 487                 d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
 488                 goto done;
 489         }
 490 
 491         /* Get domain policy handle */
 492         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
 493                                         &connect_pol,
 494                                         MAXIMUM_ALLOWED_ACCESS,
 495                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
 496                                         &domain_pol);
 497         if (!NT_STATUS_IS_OK(result)) {
 498                 d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
 499                 goto done;
 500         }
 501 
 502         result = rpccli_samr_QueryDomainInfo(pipe_hnd, mem_ctx,
 503                                              &domain_pol,
 504                                              2,
 505                                              &info);
 506         if (NT_STATUS_IS_OK(result)) {
 507                 d_printf("Domain Name: %s\n", info->general.domain_name.string);
 508                 d_printf("Domain SID: %s\n", sid_str);
 509                 d_printf("Sequence number: %llu\n",
 510                         (unsigned long long)info->general.sequence_num);
 511                 d_printf("Num users: %u\n", info->general.num_users);
 512                 d_printf("Num domain groups: %u\n", info->general.num_groups);
 513                 d_printf("Num local groups: %u\n", info->general.num_aliases);
 514         }
 515 
 516  done:
 517         return result;
 518 }
 519 
 520 /**
 521  * 'net rpc info' entrypoint.
 522  * @param argc  Standard main() style argc.
 523  * @param argv  Standard main() style argv. Initial components are already
 524  *              stripped.
 525  **/
 526 
 527 int net_rpc_info(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 528 {
 529         if (c->display_usage) {
 530                 d_printf("Usage:\n"
 531                          "net rpc info\n"
 532                          "  Display information about the domain\n");
 533                 return 0;
 534         }
 535 
 536         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
 537                                NET_FLAGS_PDC, rpc_info_internals,
 538                                argc, argv);
 539 }
 540 
 541 /**
 542  * Fetch domain SID into the local secrets.tdb.
 543  *
 544  * All parameters are provided by the run_rpc_command function, except for
 545  * argc, argv which are passed through.
 546  *
 547  * @param domain_sid The domain sid acquired from the remote server.
 548  * @param cli A cli_state connected to the server.
 549  * @param mem_ctx Talloc context, destroyed on completion of the function.
 550  * @param argc  Standard main() style argc.
 551  * @param argv  Standard main() style argv. Initial components are already
 552  *              stripped.
 553  *
 554  * @return Normal NTSTATUS return.
 555  **/
 556 
 557 static NTSTATUS rpc_getsid_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 558                         const DOM_SID *domain_sid,
 559                         const char *domain_name,
 560                         struct cli_state *cli,
 561                         struct rpc_pipe_client *pipe_hnd,
 562                         TALLOC_CTX *mem_ctx,
 563                         int argc,
 564                         const char **argv)
 565 {
 566         fstring sid_str;
 567 
 568         sid_to_fstring(sid_str, domain_sid);
 569         d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
 570                  sid_str, domain_name);
 571 
 572         if (!secrets_store_domain_sid(domain_name, domain_sid)) {
 573                 DEBUG(0,("Can't store domain SID\n"));
 574                 return NT_STATUS_UNSUCCESSFUL;
 575         }
 576 
 577         return NT_STATUS_OK;
 578 }
 579 
 580 /**
 581  * 'net rpc getsid' entrypoint.
 582  * @param argc  Standard main() style argc.
 583  * @param argv  Standard main() style argv. Initial components are already
 584  *              stripped.
 585  **/
 586 
 587 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 588 {
 589         if (c->display_usage) {
 590                 d_printf("Usage:\n"
 591                          "net rpc getsid\n"
 592                          "    Fetch domain SID into local secrets.tdb\n");
 593                 return 0;
 594         }
 595 
 596         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
 597                                NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
 598                                rpc_getsid_internals,
 599                                argc, argv);
 600 }
 601 
 602 /****************************************************************************/
 603 
 604 /**
 605  * Basic usage function for 'net rpc user'.
 606  * @param argc  Standard main() style argc.
 607  * @param argv  Standard main() style argv. Initial components are already
 608  *              stripped.
 609  **/
 610 
 611 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 612 {
 613         return net_user_usage(c, argc, argv);
 614 }
 615 
 616 /**
 617  * Add a new user to a remote RPC server.
 618  *
 619  * @param argc  Standard main() style argc.
 620  * @param argv  Standard main() style argv. Initial components are already
 621  *              stripped.
 622  *
 623  * @return A shell status integer (0 for success).
 624  **/
 625 
 626 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 627 {
 628         NET_API_STATUS status;
 629         struct USER_INFO_1 info1;
 630         uint32_t parm_error = 0;
 631 
 632         if (argc < 1 || c->display_usage) {
 633                 rpc_user_usage(c, argc, argv);
 634                 return 0;
 635         }
 636 
 637         ZERO_STRUCT(info1);
 638 
 639         info1.usri1_name = argv[0];
 640         if (argc == 2) {
 641                 info1.usri1_password = argv[1];
 642         }
 643 
 644         status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
 645 
 646         if (status != 0) {
 647                 d_fprintf(stderr, "Failed to add user '%s' with: %s.\n",
 648                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
 649                                                             status));
 650                 return -1;
 651         } else {
 652                 d_printf("Added user '%s'.\n", argv[0]);
 653         }
 654 
 655         return 0;
 656 }
 657 
 658 /**
 659  * Rename a user on a remote RPC server.
 660  *
 661  * @param argc  Standard main() style argc.
 662  * @param argv  Standard main() style argv. Initial components are already
 663  *              stripped.
 664  *
 665  * @return A shell status integer (0 for success).
 666  **/
 667 
 668 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 669 {
 670         NET_API_STATUS status;
 671         struct USER_INFO_0 u0;
 672         uint32_t parm_err = 0;
 673 
 674         if (argc != 2 || c->display_usage) {
 675                 rpc_user_usage(c, argc, argv);
 676                 return 0;
 677         }
 678 
 679         u0.usri0_name = argv[1];
 680 
 681         status = NetUserSetInfo(c->opt_host, argv[0],
 682                                 0, (uint8_t *)&u0, &parm_err);
 683         if (status) {
 684                 d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n",
 685                           argv[0], argv[1],
 686                           libnetapi_get_error_string(c->netapi_ctx, status));
 687         } else {
 688                 d_printf("Renamed user from %s to %s\n", argv[0], argv[1]);
 689         }
 690 
 691         return status;
 692 }
 693 
 694 /**
 695  * Delete a user from a remote RPC server.
 696  *
 697  * @param argc  Standard main() style argc.
 698  * @param argv  Standard main() style argv. Initial components are already
 699  *              stripped.
 700  *
 701  * @return A shell status integer (0 for success).
 702  **/
 703 
 704 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 705 {
 706         NET_API_STATUS status;
 707 
 708         if (argc < 1 || c->display_usage) {
 709                 rpc_user_usage(c, argc, argv);
 710                 return 0;
 711         }
 712 
 713         status = NetUserDel(c->opt_host, argv[0]);
 714 
 715         if (status != 0) {
 716                 d_fprintf(stderr, "Failed to delete user '%s' with: %s.\n",
 717                           argv[0],
 718                           libnetapi_get_error_string(c->netapi_ctx, status));
 719                 return -1;
 720         } else {
 721                 d_printf("Deleted user '%s'.\n", argv[0]);
 722         }
 723 
 724         return 0;
 725 }
 726 
 727 /**
 728  * Set a user's password on a remote RPC server.
 729  *
 730  * @param argc  Standard main() style argc.
 731  * @param argv  Standard main() style argv. Initial components are already
 732  *              stripped.
 733  *
 734  * @return A shell status integer (0 for success).
 735  **/
 736 
 737 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 738 {
 739         NET_API_STATUS status;
 740         char *prompt = NULL;
 741         struct USER_INFO_1003 u1003;
 742         uint32_t parm_err = 0;
 743 
 744         if (argc < 1 || c->display_usage) {
 745                 rpc_user_usage(c, argc, argv);
 746                 return 0;
 747         }
 748 
 749         if (argv[1]) {
 750                 u1003.usri1003_password = argv[1];
 751         } else {
 752                 if (asprintf(&prompt, "Enter new password for %s:", argv[0]) == -1) {
 753                         return -1;
 754                 }
 755                 u1003.usri1003_password = getpass(prompt);
 756                 SAFE_FREE(prompt);
 757         }
 758 
 759         status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
 760 
 761         /* Display results */
 762         if (status != 0) {
 763                 d_fprintf(stderr, "Failed to set password for '%s' with: %s.\n",
 764                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
 765                                                             status));
 766                 return -1;
 767         }
 768 
 769         return 0;
 770 }
 771 
 772 /**
 773  * List a user's groups from a remote RPC server.
 774  *
 775  * @param argc  Standard main() style argc.
 776  * @param argv  Standard main() style argv. Initial components are already
 777  *              stripped.
 778  *
 779  * @return A shell status integer (0 for success)
 780  **/
 781 
 782 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 783 
 784 {
 785         NET_API_STATUS status;
 786         struct GROUP_USERS_INFO_0 *u0 = NULL;
 787         uint32_t entries_read = 0;
 788         uint32_t total_entries = 0;
 789         int i;
 790 
 791 
 792         if (argc < 1 || c->display_usage) {
 793                 rpc_user_usage(c, argc, argv);
 794                 return 0;
 795         }
 796 
 797         status = NetUserGetGroups(c->opt_host,
 798                                   argv[0],
 799                                   0,
 800                                   (uint8_t **)(void *)&u0,
 801                                   (uint32_t)-1,
 802                                   &entries_read,
 803                                   &total_entries);
 804         if (status != 0) {
 805                 d_fprintf(stderr, "Failed to get groups for '%s' with: %s.\n",
 806                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
 807                                                             status));
 808                 return -1;
 809         }
 810 
 811         for (i=0; i < entries_read; i++) {
 812                 printf("%s\n", u0->grui0_name);
 813                 u0++;
 814         }
 815 
 816         return 0;
 817 }
 818 
 819 /**
 820  * List users on a remote RPC server.
 821  *
 822  * All parameters are provided by the run_rpc_command function, except for
 823  * argc, argv which are passed through.
 824  *
 825  * @param domain_sid The domain sid acquired from the remote server.
 826  * @param cli A cli_state connected to the server.
 827  * @param mem_ctx Talloc context, destroyed on completion of the function.
 828  * @param argc  Standard main() style argc.
 829  * @param argv  Standard main() style argv. Initial components are already
 830  *              stripped.
 831  *
 832  * @return Normal NTSTATUS return.
 833  **/
 834 
 835 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 836 {
 837         NET_API_STATUS status;
 838         uint32_t start_idx=0, num_entries, i, loop_count = 0;
 839         struct NET_DISPLAY_USER *info = NULL;
 840         void *buffer = NULL;
 841 
 842         /* Query domain users */
 843         if (c->opt_long_list_entries)
 844                 d_printf("\nUser name             Comment"
 845                          "\n-----------------------------\n");
 846         do {
 847                 uint32_t max_entries, max_size;
 848 
 849                 get_query_dispinfo_params(
 850                         loop_count, &max_entries, &max_size);
 851 
 852                 status = NetQueryDisplayInformation(c->opt_host,
 853                                                     1,
 854                                                     start_idx,
 855                                                     max_entries,
 856                                                     max_size,
 857                                                     &num_entries,
 858                                                     &buffer);
 859                 if (status != 0 && status != ERROR_MORE_DATA) {
 860                         return status;
 861                 }
 862 
 863                 info = (struct NET_DISPLAY_USER *)buffer;
 864 
 865                 for (i = 0; i < num_entries; i++) {
 866 
 867                         if (c->opt_long_list_entries)
 868                                 printf("%-21.21s %s\n", info->usri1_name,
 869                                         info->usri1_comment);
 870                         else
 871                                 printf("%s\n", info->usri1_name);
 872                         info++;
 873                 }
 874 
 875                 NetApiBufferFree(buffer);
 876 
 877                 loop_count++;
 878                 start_idx += num_entries;
 879 
 880         } while (status == ERROR_MORE_DATA);
 881 
 882         return status;
 883 }
 884 
 885 /**
 886  * 'net rpc user' entrypoint.
 887  * @param argc  Standard main() style argc.
 888  * @param argv  Standard main() style argv. Initial components are already
 889  *              stripped.
 890  **/
 891 
 892 int net_rpc_user(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 893 {
 894         NET_API_STATUS status;
 895 
 896         struct functable func[] = {
 897                 {
 898                         "add",
 899                         rpc_user_add,
 900                         NET_TRANSPORT_RPC,
 901                         "Add specified user",
 902                         "net rpc user add\n"
 903                         "    Add specified user"
 904                 },
 905                 {
 906                         "info",
 907                         rpc_user_info,
 908                         NET_TRANSPORT_RPC,
 909                         "List domain groups of user",
 910                         "net rpc user info\n"
 911                         "    Lis domain groups of user"
 912                 },
 913                 {
 914                         "delete",
 915                         rpc_user_delete,
 916                         NET_TRANSPORT_RPC,
 917                         "Remove specified user",
 918                         "net rpc user delete\n"
 919                         "    Remove specified user"
 920                 },
 921                 {
 922                         "password",
 923                         rpc_user_password,
 924                         NET_TRANSPORT_RPC,
 925                         "Change user password",
 926                         "net rpc user password\n"
 927                         "    Change user password"
 928                 },
 929                 {
 930                         "rename",
 931                         rpc_user_rename,
 932                         NET_TRANSPORT_RPC,
 933                         "Rename specified user",
 934                         "net rpc user rename\n"
 935                         "    Rename specified user"
 936                 },
 937                 {NULL, NULL, 0, NULL, NULL}
 938         };
 939 
 940         status = libnetapi_init(&c->netapi_ctx);
 941         if (status != 0) {
 942                 return -1;
 943         }
 944         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
 945         libnetapi_set_password(c->netapi_ctx, c->opt_password);
 946         if (c->opt_kerberos) {
 947                 libnetapi_set_use_kerberos(c->netapi_ctx);
 948         }
 949 
 950         if (argc == 0) {
 951                 if (c->display_usage) {
 952                         d_printf("Usage:\n");
 953                         d_printf("net rpc user\n"
 954                                  "    List all users\n");
 955                         net_display_usage_from_functable(func);
 956                         return 0;
 957                 }
 958 
 959                 return rpc_user_list(c, argc, argv);
 960         }
 961 
 962         return net_run_function(c, argc, argv, "net rpc user", func);
 963 }
 964 
 965 static NTSTATUS rpc_sh_user_list(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 966                                  TALLOC_CTX *mem_ctx,
 967                                  struct rpc_sh_ctx *ctx,
 968                                  struct rpc_pipe_client *pipe_hnd,
 969                                  int argc, const char **argv)
 970 {
 971         return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
 972 }
 973 
 974 static NTSTATUS rpc_sh_user_info(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 975                                  TALLOC_CTX *mem_ctx,
 976                                  struct rpc_sh_ctx *ctx,
 977                                  struct rpc_pipe_client *pipe_hnd,
 978                                  int argc, const char **argv)
 979 {
 980         return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
 981 }
 982 
 983 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 984                                    TALLOC_CTX *mem_ctx,
 985                                    struct rpc_sh_ctx *ctx,
 986                                    struct rpc_pipe_client *pipe_hnd,
 987                                    int argc, const char **argv,
 988                                    NTSTATUS (*fn)(
 989                                            struct net_context *c,
 990                                            TALLOC_CTX *mem_ctx,
 991                                            struct rpc_sh_ctx *ctx,
 992                                            struct rpc_pipe_client *pipe_hnd,
 993                                            struct policy_handle *user_hnd,
 994                                            int argc, const char **argv))
 995 {
 996         struct policy_handle connect_pol, domain_pol, user_pol;
 997         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 998         DOM_SID sid;
 999         uint32 rid;
1000         enum lsa_SidType type;
1001 
1002         if (argc == 0) {
1003                 d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
1004                 return NT_STATUS_INVALID_PARAMETER;
1005         }
1006 
1007         ZERO_STRUCT(connect_pol);
1008         ZERO_STRUCT(domain_pol);
1009         ZERO_STRUCT(user_pol);
1010 
1011         result = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1012                                      argv[0], NULL, NULL, &sid, &type);
1013         if (!NT_STATUS_IS_OK(result)) {
1014                 d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
1015                           nt_errstr(result));
1016                 goto done;
1017         }
1018 
1019         if (type != SID_NAME_USER) {
1020                 d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
1021                           sid_type_lookup(type));
1022                 result = NT_STATUS_NO_SUCH_USER;
1023                 goto done;
1024         }
1025 
1026         if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1027                 d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
1028                 result = NT_STATUS_NO_SUCH_USER;
1029                 goto done;
1030         }
1031 
1032         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1033                                       pipe_hnd->desthost,
1034                                       MAXIMUM_ALLOWED_ACCESS,
1035                                       &connect_pol);
1036         if (!NT_STATUS_IS_OK(result)) {
1037                 goto done;
1038         }
1039 
1040         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1041                                         &connect_pol,
1042                                         MAXIMUM_ALLOWED_ACCESS,
1043                                         ctx->domain_sid,
1044                                         &domain_pol);
1045         if (!NT_STATUS_IS_OK(result)) {
1046                 goto done;
1047         }
1048 
1049         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1050                                       &domain_pol,
1051                                       MAXIMUM_ALLOWED_ACCESS,
1052                                       rid,
1053                                       &user_pol);
1054         if (!NT_STATUS_IS_OK(result)) {
1055                 goto done;
1056         }
1057 
1058         result = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1059 
1060  done:
1061         if (is_valid_policy_hnd(&user_pol)) {
1062                 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1063         }
1064         if (is_valid_policy_hnd(&domain_pol)) {
1065                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
1066         }
1067         if (is_valid_policy_hnd(&connect_pol)) {
1068                 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1069         }
1070         return result;
1071 }
1072 
1073 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1074                                            TALLOC_CTX *mem_ctx,
1075                                            struct rpc_sh_ctx *ctx,
1076                                            struct rpc_pipe_client *pipe_hnd,
1077                                            struct policy_handle *user_hnd,
1078                                            int argc, const char **argv)
1079 {
1080         NTSTATUS result;
1081         union samr_UserInfo *info = NULL;
1082 
1083         if (argc != 0) {
1084                 d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
1085                 return NT_STATUS_INVALID_PARAMETER;
1086         }
1087 
1088         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1089                                            user_hnd,
1090                                            21,
1091                                            &info);
1092         if (!NT_STATUS_IS_OK(result)) {
1093                 return result;
1094         }
1095 
1096         d_printf("user rid: %d, group rid: %d\n",
1097                 info->info21.rid,
1098                 info->info21.primary_gid);
1099 
1100         return result;
1101 }
1102 
1103 static NTSTATUS rpc_sh_user_show(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1104                                  TALLOC_CTX *mem_ctx,
1105                                  struct rpc_sh_ctx *ctx,
1106                                  struct rpc_pipe_client *pipe_hnd,
1107                                  int argc, const char **argv)
1108 {
1109         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1110                                   rpc_sh_user_show_internals);
1111 }
1112 
1113 #define FETCHSTR(name, rec) \
1114 do { if (strequal(ctx->thiscmd, name)) { \
1115         oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1116 } while (0);
1117 
1118 #define SETSTR(name, rec, flag) \
1119 do { if (strequal(ctx->thiscmd, name)) { \
1120         init_lsa_String(&(info->info21.rec), argv[0]); \
1121         info->info21.fields_present |= SAMR_FIELD_##flag; } \
1122 } while (0);
1123 
1124 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1125                                                TALLOC_CTX *mem_ctx,
1126                                                struct rpc_sh_ctx *ctx,
1127                                                struct rpc_pipe_client *pipe_hnd,
1128                                                struct policy_handle *user_hnd,
1129                                                int argc, const char **argv)
1130 {
1131         NTSTATUS result;
1132         const char *username;
1133         const char *oldval = "";
1134         union samr_UserInfo *info = NULL;
1135 
1136         if (argc > 1) {
1137                 d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
1138                           ctx->whoami);
1139                 return NT_STATUS_INVALID_PARAMETER;
1140         }
1141 
1142         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1143                                            user_hnd,
1144                                            21,
1145                                            &info);
1146         if (!NT_STATUS_IS_OK(result)) {
1147                 return result;
1148         }
1149 
1150         username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1151 
1152         FETCHSTR("fullname", full_name);
1153         FETCHSTR("homedir", home_directory);
1154         FETCHSTR("homedrive", home_drive);
1155         FETCHSTR("logonscript", logon_script);
1156         FETCHSTR("profilepath", profile_path);
1157         FETCHSTR("description", description);
1158 
1159         if (argc == 0) {
1160                 d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
1161                 goto done;
1162         }
1163 
1164         if (strcmp(argv[0], "NULL") == 0) {
1165                 argv[0] = "";
1166         }
1167 
1168         ZERO_STRUCT(info->info21);
1169 
1170         SETSTR("fullname", full_name, FULL_NAME);
1171         SETSTR("homedir", home_directory, HOME_DIRECTORY);
1172         SETSTR("homedrive", home_drive, HOME_DRIVE);
1173         SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1174         SETSTR("profilepath", profile_path, PROFILE_PATH);
1175         SETSTR("description", description, DESCRIPTION);
1176 
1177         result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1178                                          user_hnd,
1179                                          21,
1180                                          info);
1181 
1182         d_printf("Set %s's %s from [%s] to [%s]\n", username,
1183                  ctx->thiscmd, oldval, argv[0]);
1184 
1185  done:
1186 
1187         return result;
1188 }
1189 
1190 #define HANDLEFLG(name, rec) \
1191 do { if (strequal(ctx->thiscmd, name)) { \
1192         oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1193         if (newval) { \
1194                 newflags = oldflags | ACB_##rec; \
1195         } else { \
1196                 newflags = oldflags & ~ACB_##rec; \
1197         } } } while (0);
1198 
1199 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1200                                      TALLOC_CTX *mem_ctx,
1201                                      struct rpc_sh_ctx *ctx,
1202                                      struct rpc_pipe_client *pipe_hnd,
1203                                      int argc, const char **argv)
1204 {
1205         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1206                                   rpc_sh_user_str_edit_internals);
1207 }
1208 
1209 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1210                                                 TALLOC_CTX *mem_ctx,
1211                                                 struct rpc_sh_ctx *ctx,
1212                                                 struct rpc_pipe_client *pipe_hnd,
1213                                                 struct policy_handle *user_hnd,
1214                                                 int argc, const char **argv)
1215 {
1216         NTSTATUS result;
1217         const char *username;
1218         const char *oldval = "unknown";
1219         uint32 oldflags, newflags;
1220         bool newval;
1221         union samr_UserInfo *info = NULL;
1222 
1223         if ((argc > 1) ||
1224             ((argc == 1) && !strequal(argv[0], "yes") &&
1225              !strequal(argv[0], "no"))) {
1226                 d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
1227                           ctx->whoami);
1228                 return NT_STATUS_INVALID_PARAMETER;
1229         }
1230 
1231         newval = strequal(argv[0], "yes");
1232 
1233         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1234                                            user_hnd,
1235                                            21,
1236                                            &info);
1237         if (!NT_STATUS_IS_OK(result)) {
1238                 return result;
1239         }
1240 
1241         username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1242         oldflags = info->info21.acct_flags;
1243         newflags = info->info21.acct_flags;
1244 
1245         HANDLEFLG("disabled", DISABLED);
1246         HANDLEFLG("pwnotreq", PWNOTREQ);
1247         HANDLEFLG("autolock", AUTOLOCK);
1248         HANDLEFLG("pwnoexp", PWNOEXP);
1249 
1250         if (argc == 0) {
1251                 d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
1252                 goto done;
1253         }
1254 
1255         ZERO_STRUCT(info->info21);
1256 
1257         info->info21.acct_flags = newflags;
1258         info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1259 
1260         result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1261                                          user_hnd,
1262                                          21,
1263                                          info);
1264 
1265         if (NT_STATUS_IS_OK(result)) {
1266                 d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
1267                          ctx->thiscmd, oldval, argv[0]);
1268         }
1269 
1270  done:
1271 
1272         return result;
1273 }
1274 
1275 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1276                                       TALLOC_CTX *mem_ctx,
1277                                       struct rpc_sh_ctx *ctx,
1278                                       struct rpc_pipe_client *pipe_hnd,
1279                                       int argc, const char **argv)
1280 {
1281         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1282                                   rpc_sh_user_flag_edit_internals);
1283 }
1284 
1285 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1286                                           TALLOC_CTX *mem_ctx,
1287                                           struct rpc_sh_ctx *ctx)
1288 {
1289         static struct rpc_sh_cmd cmds[] = {
1290 
1291                 { "fullname", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1292                   "Show/Set a user's full name" },
1293 
1294                 { "homedir", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1295                   "Show/Set a user's home directory" },
1296 
1297                 { "homedrive", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1298                   "Show/Set a user's home drive" },
1299 
1300                 { "logonscript", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1301                   "Show/Set a user's logon script" },
1302 
1303                 { "profilepath", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1304                   "Show/Set a user's profile path" },
1305 
1306                 { "description", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1307                   "Show/Set a user's description" },
1308 
1309                 { "disabled", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1310                   "Show/Set whether a user is disabled" },
1311 
1312                 { "autolock", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1313                   "Show/Set whether a user locked out" },
1314 
1315                 { "pwnotreq", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1316                   "Show/Set whether a user does not need a password" },
1317 
1318                 { "pwnoexp", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1319                   "Show/Set whether a user's password does not expire" },
1320 
1321                 { NULL, NULL, 0, NULL, NULL }
1322         };
1323 
1324         return cmds;
1325 }
1326 
1327 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1328                                      TALLOC_CTX *mem_ctx,
1329                                      struct rpc_sh_ctx *ctx)
1330 {
1331         static struct rpc_sh_cmd cmds[] = {
1332 
1333                 { "list", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_list,
1334                   "List available users" },
1335 
1336                 { "info", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_info,
1337                   "List the domain groups a user is member of" },
1338 
1339                 { "show", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_show,
1340                   "Show info about a user" },
1341 
1342                 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1343                   "Show/Modify a user's fields" },
1344 
1345                 { NULL, NULL, 0, NULL, NULL }
1346         };
1347 
1348         return cmds;
1349 }
1350 
1351 /****************************************************************************/
1352 
1353 /**
1354  * Basic usage function for 'net rpc group'.
1355  * @param argc  Standard main() style argc.
1356  * @param argv  Standard main() style argv. Initial components are already
1357  *              stripped.
1358  **/
1359 
1360 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1361 {
1362         return net_group_usage(c, argc, argv);
1363 }
1364 
1365 /**
1366  * Delete group on a remote RPC server.
1367  *
1368  * All parameters are provided by the run_rpc_command function, except for
1369  * argc, argv which are passed through.
1370  *
1371  * @param domain_sid The domain sid acquired from the remote server.
1372  * @param cli A cli_state connected to the server.
1373  * @param mem_ctx Talloc context, destroyed on completion of the function.
1374  * @param argc  Standard main() style argc.
1375  * @param argv  Standard main() style argv. Initial components are already
1376  *              stripped.
1377  *
1378  * @return Normal NTSTATUS return.
1379  **/
1380 
1381 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1382                                         const DOM_SID *domain_sid,
1383                                         const char *domain_name,
1384                                         struct cli_state *cli,
1385                                         struct rpc_pipe_client *pipe_hnd,
1386                                         TALLOC_CTX *mem_ctx,
1387                                         int argc,
1388                                         const char **argv)
1389 {
1390         struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1391         bool group_is_primary = false;
1392         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1393         uint32_t group_rid;
1394         struct samr_RidTypeArray *rids = NULL;
1395         /* char **names; */
1396         int i;
1397         /* struct samr_RidWithAttribute *user_gids; */
1398 
1399         struct samr_Ids group_rids, name_types;
1400         struct lsa_String lsa_acct_name;
1401         union samr_UserInfo *info = NULL;
1402 
1403         if (argc < 1 || c->display_usage) {
1404                 rpc_group_usage(c, argc,argv);
1405                 return NT_STATUS_OK; /* ok? */
1406         }
1407 
1408         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1409                                       pipe_hnd->desthost,
1410                                       MAXIMUM_ALLOWED_ACCESS,
1411                                       &connect_pol);
1412 
1413         if (!NT_STATUS_IS_OK(result)) {
1414                 d_fprintf(stderr, "Request samr_Connect2 failed\n");
1415                 goto done;
1416         }
1417 
1418         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1419                                         &connect_pol,
1420                                         MAXIMUM_ALLOWED_ACCESS,
1421                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1422                                         &domain_pol);
1423 
1424         if (!NT_STATUS_IS_OK(result)) {
1425                 d_fprintf(stderr, "Request open_domain failed\n");
1426                 goto done;
1427         }
1428 
1429         init_lsa_String(&lsa_acct_name, argv[0]);
1430 
1431         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1432                                          &domain_pol,
1433                                          1,
1434                                          &lsa_acct_name,
1435                                          &group_rids,
1436                                          &name_types);
1437         if (!NT_STATUS_IS_OK(result)) {
1438                 d_fprintf(stderr, "Lookup of '%s' failed\n",argv[0]);
1439                 goto done;
1440         }
1441 
1442         switch (name_types.ids[0])
1443         {
1444         case SID_NAME_DOM_GRP:
1445                 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1446                                                &domain_pol,
1447                                                MAXIMUM_ALLOWED_ACCESS,
1448                                                group_rids.ids[0],
1449                                                &group_pol);
1450                 if (!NT_STATUS_IS_OK(result)) {
1451                         d_fprintf(stderr, "Request open_group failed");
1452                         goto done;
1453                 }
1454 
1455                 group_rid = group_rids.ids[0];
1456 
1457                 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
1458                                                       &group_pol,
1459                                                       &rids);
1460 
1461                 if (!NT_STATUS_IS_OK(result)) {
1462                         d_fprintf(stderr, "Unable to query group members of %s",argv[0]);
1463                         goto done;
1464                 }
1465 
1466                 if (c->opt_verbose) {
1467                         d_printf("Domain Group %s (rid: %d) has %d members\n",
1468                                 argv[0],group_rid, rids->count);
1469                 }
1470 
1471                 /* Check if group is anyone's primary group */
1472                 for (i = 0; i < rids->count; i++)
1473                 {
1474                         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1475                                                       &domain_pol,
1476                                                       MAXIMUM_ALLOWED_ACCESS,
1477                                                       rids->rids[i],
1478                                                       &user_pol);
1479 
1480                         if (!NT_STATUS_IS_OK(result)) {
1481                                 d_fprintf(stderr, "Unable to open group member %d\n",
1482                                         rids->rids[i]);
1483                                 goto done;
1484                         }
1485 
1486                         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1487                                                            &user_pol,
1488                                                            21,
1489                                                            &info);
1490 
1491                         if (!NT_STATUS_IS_OK(result)) {
1492                                 d_fprintf(stderr, "Unable to lookup userinfo for group member %d\n",
1493                                         rids->rids[i]);
1494                                 goto done;
1495                         }
1496 
1497                         if (info->info21.primary_gid == group_rid) {
1498                                 if (c->opt_verbose) {
1499                                         d_printf("Group is primary group of %s\n",
1500                                                 info->info21.account_name.string);
1501                                 }
1502                                 group_is_primary = true;
1503                         }
1504 
1505                         rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1506                 }
1507 
1508                 if (group_is_primary) {
1509                         d_fprintf(stderr, "Unable to delete group because some "
1510                                  "of it's members have it as primary group\n");
1511                         result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1512                         goto done;
1513                 }
1514 
1515                 /* remove all group members */
1516                 for (i = 0; i < rids->count; i++)
1517                 {
1518                         if (c->opt_verbose)
1519                                 d_printf("Remove group member %d...",
1520                                         rids->rids[i]);
1521                         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1522                                                                &group_pol,
1523                                                                rids->rids[i]);
1524 
1525                         if (NT_STATUS_IS_OK(result)) {
1526                                 if (c->opt_verbose)
1527                                         d_printf("ok\n");
1528                         } else {
1529                                 if (c->opt_verbose)
1530                                         d_printf("failed\n");
1531                                 goto done;
1532                         }
1533                 }
1534 
1535                 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1536                                                        &group_pol);
1537 
1538                 break;
1539         /* removing a local group is easier... */
1540         case SID_NAME_ALIAS:
1541                 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1542                                                &domain_pol,
1543                                                MAXIMUM_ALLOWED_ACCESS,
1544                                                group_rids.ids[0],
1545                                                &group_pol);
1546 
1547                 if (!NT_STATUS_IS_OK(result)) {
1548                         d_fprintf(stderr, "Request open_alias failed\n");
1549                         goto done;
1550                 }
1551 
1552                 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1553                                                     &group_pol);
1554                 break;
1555         default:
1556                 d_fprintf(stderr, "%s is of type %s. This command is only for deleting local or global groups\n",
1557                         argv[0],sid_type_lookup(name_types.ids[0]));
1558                 result = NT_STATUS_UNSUCCESSFUL;
1559                 goto done;
1560         }
1561 
1562         if (NT_STATUS_IS_OK(result)) {
1563                 if (c->opt_verbose)
1564                         d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types.ids[0]),argv[0]);
1565         } else {
1566                 d_fprintf(stderr, "Deleting of %s failed: %s\n",argv[0],
1567                         get_friendly_nt_error_msg(result));
1568         }
1569 
1570  done:
1571         return result;
1572 
1573 }
1574 
1575 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1576 {
1577         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1578                                rpc_group_delete_internals, argc,argv);
1579 }
1580 
1581 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1582 {
1583         NET_API_STATUS status;
1584         struct GROUP_INFO_1 info1;
1585         uint32_t parm_error = 0;
1586 
1587         if (argc != 1 || c->display_usage) {
1588                 rpc_group_usage(c, argc, argv);
1589                 return 0;
1590         }
1591 
1592         ZERO_STRUCT(info1);
1593 
1594         info1.grpi1_name = argv[0];
1595         if (c->opt_comment && strlen(c->opt_comment) > 0) {
1596                 info1.grpi1_comment = c->opt_comment;
1597         }
1598 
1599         status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1600 
1601         if (status != 0) {
1602                 d_fprintf(stderr, "Failed to add group '%s' with: %s.\n",
1603                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
1604                                                             status));
1605                 return -1;
1606         } else {
1607                 d_printf("Added group '%s'.\n", argv[0]);
1608         }
1609 
1610         return 0;
1611 }
1612 
1613 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1614 {
1615         NET_API_STATUS status;
1616         struct LOCALGROUP_INFO_1 info1;
1617         uint32_t parm_error = 0;
1618 
1619         if (argc != 1 || c->display_usage) {
1620                 rpc_group_usage(c, argc, argv);
1621                 return 0;
1622         }
1623 
1624         ZERO_STRUCT(info1);
1625 
1626         info1.lgrpi1_name = argv[0];
1627         if (c->opt_comment && strlen(c->opt_comment) > 0) {
1628                 info1.lgrpi1_comment = c->opt_comment;
1629         }
1630 
1631         status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1632 
1633         if (status != 0) {
1634                 d_fprintf(stderr, "Failed to add alias '%s' with: %s.\n",
1635                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
1636                                                             status));
1637                 return -1;
1638         } else {
1639                 d_printf("Added alias '%s'.\n", argv[0]);
1640         }
1641 
1642         return 0;
1643 }
1644 
1645 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1646 {
1647         if (c->opt_localgroup)
1648                 return rpc_alias_add_internals(c, argc, argv);
1649 
1650         return rpc_group_add_internals(c, argc, argv);
1651 }
1652 
1653 static NTSTATUS get_sid_from_name(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
1654                                 TALLOC_CTX *mem_ctx,
1655                                 const char *name,
1656                                 DOM_SID *sid,
1657                                 enum lsa_SidType *type)
1658 {
1659         DOM_SID *sids = NULL;
1660         enum lsa_SidType *types = NULL;
1661         struct rpc_pipe_client *pipe_hnd = NULL;
1662         struct policy_handle lsa_pol;
1663         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1664 
1665         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1666                                           &pipe_hnd);
1667         if (!NT_STATUS_IS_OK(result)) {
1668                 goto done;
1669         }
1670 
1671         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1672                                      SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1673 
1674         if (!NT_STATUS_IS_OK(result)) {
1675                 goto done;
1676         }
1677 
1678         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1679                                       &name, NULL, 1, &sids, &types);
1680 
1681         if (NT_STATUS_IS_OK(result)) {
1682                 sid_copy(sid, &sids[0]);
1683                 *type = types[0];
1684         }
1685 
1686         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
1687 
1688  done:
1689         if (pipe_hnd) {
1690                 TALLOC_FREE(pipe_hnd);
1691         }
1692 
1693         if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1694 
1695                 /* Try as S-1-5-whatever */
1696 
1697                 DOM_SID tmp_sid;
1698 
1699                 if (string_to_sid(&tmp_sid, name)) {
1700                         sid_copy(sid, &tmp_sid);
1701                         *type = SID_NAME_UNKNOWN;
1702                         result = NT_STATUS_OK;
1703                 }
1704         }
1705 
1706         return result;
1707 }
1708 
1709 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
1710                                 TALLOC_CTX *mem_ctx,
1711                                 const DOM_SID *group_sid,
1712                                 const char *member)
1713 {
1714         struct policy_handle connect_pol, domain_pol;
1715         NTSTATUS result;
1716         uint32 group_rid;
1717         struct policy_handle group_pol;
1718 
1719         struct samr_Ids rids, rid_types;
1720         struct lsa_String lsa_acct_name;
1721 
1722         DOM_SID sid;
1723 
1724         sid_copy(&sid, group_sid);
1725 
1726         if (!sid_split_rid(&sid, &group_rid)) {
1727                 return NT_STATUS_UNSUCCESSFUL;
1728         }
1729 
1730         /* Get sam policy handle */
1731         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1732                                       pipe_hnd->desthost,
1733                                       MAXIMUM_ALLOWED_ACCESS,
1734                                       &connect_pol);
1735         if (!NT_STATUS_IS_OK(result)) {
1736                 return result;
1737         }
1738 
1739         /* Get domain policy handle */
1740         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1741                                         &connect_pol,
1742                                         MAXIMUM_ALLOWED_ACCESS,
1743                                         &sid,
1744                                         &domain_pol);
1745         if (!NT_STATUS_IS_OK(result)) {
1746                 return result;
1747         }
1748 
1749         init_lsa_String(&lsa_acct_name, member);
1750 
1751         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1752                                          &domain_pol,
1753                                          1,
1754                                          &lsa_acct_name,
1755                                          &rids,
1756                                          &rid_types);
1757 
1758         if (!NT_STATUS_IS_OK(result)) {
1759                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
1760                 goto done;
1761         }
1762 
1763         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1764                                        &domain_pol,
1765                                        MAXIMUM_ALLOWED_ACCESS,
1766                                        group_rid,
1767                                        &group_pol);
1768 
1769         if (!NT_STATUS_IS_OK(result)) {
1770                 goto done;
1771         }
1772 
1773         result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
1774                                             &group_pol,
1775                                             rids.ids[0],
1776                                             0x0005); /* unknown flags */
1777 
1778  done:
1779         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1780         return result;
1781 }
1782 
1783 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
1784                                 TALLOC_CTX *mem_ctx,
1785                                 const DOM_SID *alias_sid,
1786                                 const char *member)
1787 {
1788         struct policy_handle connect_pol, domain_pol;
1789         NTSTATUS result;
1790         uint32 alias_rid;
1791         struct policy_handle alias_pol;
1792 
1793         DOM_SID member_sid;
1794         enum lsa_SidType member_type;
1795 
1796         DOM_SID sid;
1797 
1798         sid_copy(&sid, alias_sid);
1799 
1800         if (!sid_split_rid(&sid, &alias_rid)) {
1801                 return NT_STATUS_UNSUCCESSFUL;
1802         }
1803 
1804         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
1805                                    member, &member_sid, &member_type);
1806 
1807         if (!NT_STATUS_IS_OK(result)) {
1808                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
1809                 return result;
1810         }
1811 
1812         /* Get sam policy handle */
1813         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1814                                       pipe_hnd->desthost,
1815                                       MAXIMUM_ALLOWED_ACCESS,
1816                                       &connect_pol);
1817         if (!NT_STATUS_IS_OK(result)) {
1818                 goto done;
1819         }
1820 
1821         /* Get domain policy handle */
1822         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1823                                         &connect_pol,
1824                                         MAXIMUM_ALLOWED_ACCESS,
1825                                         &sid,
1826                                         &domain_pol);
1827         if (!NT_STATUS_IS_OK(result)) {
1828                 goto done;
1829         }
1830 
1831         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1832                                        &domain_pol,
1833                                        MAXIMUM_ALLOWED_ACCESS,
1834                                        alias_rid,
1835                                        &alias_pol);
1836 
1837         if (!NT_STATUS_IS_OK(result)) {
1838                 return result;
1839         }
1840 
1841         result = rpccli_samr_AddAliasMember(pipe_hnd, mem_ctx,
1842                                             &alias_pol,
1843                                             &member_sid);
1844 
1845         if (!NT_STATUS_IS_OK(result)) {
1846                 return result;
1847         }
1848 
1849  done:
1850         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1851         return result;
1852 }
1853 
1854 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1855                                         const DOM_SID *domain_sid,
1856                                         const char *domain_name,
1857                                         struct cli_state *cli,
1858                                         struct rpc_pipe_client *pipe_hnd,
1859                                         TALLOC_CTX *mem_ctx,
1860                                         int argc,
1861                                         const char **argv)
1862 {
1863         DOM_SID group_sid;
1864         enum lsa_SidType group_type;
1865 
1866         if (argc != 2 || c->display_usage) {
1867                 d_printf("Usage:\n"
1868                          "net rpc group addmem <group> <member>\n"
1869                          "  Add a member to a group\n"
1870                          "    group\tGroup to add member to\n"
1871                          "    member\tMember to add to group\n");
1872                 return NT_STATUS_UNSUCCESSFUL;
1873         }
1874 
1875         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
1876                                                &group_sid, &group_type))) {
1877                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
1878                 return NT_STATUS_UNSUCCESSFUL;
1879         }
1880 
1881         if (group_type == SID_NAME_DOM_GRP) {
1882                 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
1883                                                    &group_sid, argv[1]);
1884 
1885                 if (!NT_STATUS_IS_OK(result)) {
1886                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
1887                                  argv[1], argv[0], nt_errstr(result));
1888                 }
1889                 return result;
1890         }
1891 
1892         if (group_type == SID_NAME_ALIAS) {
1893                 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
1894                                                    &group_sid, argv[1]);
1895 
1896                 if (!NT_STATUS_IS_OK(result)) {
1897                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
1898                                  argv[1], argv[0], nt_errstr(result));
1899                 }
1900                 return result;
1901         }
1902 
1903         d_fprintf(stderr, "Can only add members to global or local groups "
1904                  "which %s is not\n", argv[0]);
1905 
1906         return NT_STATUS_UNSUCCESSFUL;
1907 }
1908 
1909 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1910 {
1911         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1912                                rpc_group_addmem_internals,
1913                                argc, argv);
1914 }
1915 
1916 static NTSTATUS rpc_del_groupmem(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
1917                                 struct rpc_pipe_client *pipe_hnd,
1918                                 TALLOC_CTX *mem_ctx,
1919                                 const DOM_SID *group_sid,
1920                                 const char *member)
1921 {
1922         struct policy_handle connect_pol, domain_pol;
1923         NTSTATUS result;
1924         uint32 group_rid;
1925         struct policy_handle group_pol;
1926 
1927         struct samr_Ids rids, rid_types;
1928         struct lsa_String lsa_acct_name;
1929 
1930         DOM_SID sid;
1931 
1932         sid_copy(&sid, group_sid);
1933 
1934         if (!sid_split_rid(&sid, &group_rid))
1935                 return NT_STATUS_UNSUCCESSFUL;
1936 
1937         /* Get sam policy handle */
1938         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1939                                       pipe_hnd->desthost,
1940                                       MAXIMUM_ALLOWED_ACCESS,
1941                                       &connect_pol);
1942         if (!NT_STATUS_IS_OK(result))
1943                 return result;
1944 
1945         /* Get domain policy handle */
1946         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1947                                         &connect_pol,
1948                                         MAXIMUM_ALLOWED_ACCESS,
1949                                         &sid,
1950                                         &domain_pol);
1951         if (!NT_STATUS_IS_OK(result))
1952                 return result;
1953 
1954         init_lsa_String(&lsa_acct_name, member);
1955 
1956         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1957                                          &domain_pol,
1958                                          1,
1959                                          &lsa_acct_name,
1960                                          &rids,
1961                                          &rid_types);
1962         if (!NT_STATUS_IS_OK(result)) {
1963                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
1964                 goto done;
1965         }
1966 
1967         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1968                                        &domain_pol,
1969                                        MAXIMUM_ALLOWED_ACCESS,
1970                                        group_rid,
1971                                        &group_pol);
1972 
1973         if (!NT_STATUS_IS_OK(result))
1974                 goto done;
1975 
1976         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1977                                                &group_pol,
1978                                                rids.ids[0]);
1979 
1980  done:
1981         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1982         return result;
1983 }
1984 
1985 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
1986                                 TALLOC_CTX *mem_ctx,
1987                                 const DOM_SID *alias_sid,
1988                                 const char *member)
1989 {
1990         struct policy_handle connect_pol, domain_pol;
1991         NTSTATUS result;
1992         uint32 alias_rid;
1993         struct policy_handle alias_pol;
1994 
1995         DOM_SID member_sid;
1996         enum lsa_SidType member_type;
1997 
1998         DOM_SID sid;
1999 
2000         sid_copy(&sid, alias_sid);
2001 
2002         if (!sid_split_rid(&sid, &alias_rid))
2003                 return NT_STATUS_UNSUCCESSFUL;
2004 
2005         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2006                                    member, &member_sid, &member_type);
2007 
2008         if (!NT_STATUS_IS_OK(result)) {
2009                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2010                 return result;
2011         }
2012 
2013         /* Get sam policy handle */
2014         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2015                                       pipe_hnd->desthost,
2016                                       MAXIMUM_ALLOWED_ACCESS,
2017                                       &connect_pol);
2018         if (!NT_STATUS_IS_OK(result)) {
2019                 goto done;
2020         }
2021 
2022         /* Get domain policy handle */
2023         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2024                                         &connect_pol,
2025                                         MAXIMUM_ALLOWED_ACCESS,
2026                                         &sid,
2027                                         &domain_pol);
2028         if (!NT_STATUS_IS_OK(result)) {
2029                 goto done;
2030         }
2031 
2032         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2033                                        &domain_pol,
2034                                        MAXIMUM_ALLOWED_ACCESS,
2035                                        alias_rid,
2036                                        &alias_pol);
2037 
2038         if (!NT_STATUS_IS_OK(result))
2039                 return result;
2040 
2041         result = rpccli_samr_DeleteAliasMember(pipe_hnd, mem_ctx,
2042                                                &alias_pol,
2043                                                &member_sid);
2044 
2045         if (!NT_STATUS_IS_OK(result))
2046                 return result;
2047 
2048  done:
2049         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2050         return result;
2051 }
2052 
2053 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
2054                                         const DOM_SID *domain_sid,
2055                                         const char *domain_name,
2056                                         struct cli_state *cli,
2057                                         struct rpc_pipe_client *pipe_hnd,
2058                                         TALLOC_CTX *mem_ctx,
2059                                         int argc,
2060                                         const char **argv)
2061 {
2062         DOM_SID group_sid;
2063         enum lsa_SidType group_type;
2064 
2065         if (argc != 2 || c->display_usage) {
2066                 d_printf("Usage:\n"
2067                          "net rpc group delmem <group> <member>\n"
2068                          "  Delete a member from a group\n"
2069                          "    group\tGroup to delete member from\n"
2070                          "    member\tMember to delete from group\n");
2071                 return NT_STATUS_UNSUCCESSFUL;
2072         }
2073 
2074         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2075                                                &group_sid, &group_type))) {
2076                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2077                 return NT_STATUS_UNSUCCESSFUL;
2078         }
2079 
2080         if (group_type == SID_NAME_DOM_GRP) {
2081                 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2082                                                    &group_sid, argv[1]);
2083 
2084                 if (!NT_STATUS_IS_OK(result)) {
2085                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2086                                  argv[1], argv[0], nt_errstr(result));
2087                 }
2088                 return result;
2089         }
2090 
2091         if (group_type == SID_NAME_ALIAS) {
2092                 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2093                                                    &group_sid, argv[1]);
2094 
2095                 if (!NT_STATUS_IS_OK(result)) {
2096                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2097                                  argv[1], argv[0], nt_errstr(result));
2098                 }
2099                 return result;
2100         }
2101 
2102         d_fprintf(stderr, "Can only delete members from global or local groups "
2103                  "which %s is not\n", argv[0]);
2104 
2105         return NT_STATUS_UNSUCCESSFUL;
2106 }
2107 
2108 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2109 {
2110         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2111                                rpc_group_delmem_internals,
2112                                argc, argv);
2113 }
2114 
2115 /**
2116  * List groups on a remote RPC server.
2117  *
2118  * All parameters are provided by the run_rpc_command function, except for
2119  * argc, argv which are passes through.
2120  *
2121  * @param domain_sid The domain sid acquired from the remote server.
2122  * @param cli A cli_state connected to the server.
2123  * @param mem_ctx Talloc context, destroyed on completion of the function.
2124  * @param argc  Standard main() style argc.
2125  * @param argv  Standard main() style argv. Initial components are already
2126  *              stripped.
2127  *
2128  * @return Normal NTSTATUS return.
2129  **/
2130 
2131 static NTSTATUS rpc_group_list_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
2132                                         const DOM_SID *domain_sid,
2133                                         const char *domain_name,
2134                                         struct cli_state *cli,
2135                                         struct rpc_pipe_client *pipe_hnd,
2136                                         TALLOC_CTX *mem_ctx,
2137                                         int argc,
2138                                         const char **argv)
2139 {
2140         struct policy_handle connect_pol, domain_pol;
2141         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2142         uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2143         struct samr_SamArray *groups = NULL;
2144         bool global = false;
2145         bool local = false;
2146         bool builtin = false;
2147 
2148         if (c->display_usage) {
2149                 d_printf("Usage:\n"
2150                          "net rpc group list [global] [local] [builtin]\n"
2151                          "  List groups on RPC server\n"
2152                          "    global\tList global groups\n"
2153                          "    local\tList local groups\n"
2154                          "    builtin\tList builtin groups\n"
2155                          "    If none of global, local or builtin is "
2156                          "specified, all three options are considered set\n");
2157                 return NT_STATUS_OK;
2158         }
2159 
2160         if (argc == 0) {
2161                 global = true;
2162                 local = true;
2163                 builtin = true;
2164         }
2165 
2166         for (i=0; i<argc; i++) {
2167                 if (strequal(argv[i], "global"))
2168                         global = true;
2169 
2170                 if (strequal(argv[i], "local"))
2171                         local = true;
2172 
2173                 if (strequal(argv[i], "builtin"))
2174                         builtin = true;
2175         }
2176 
2177         /* Get sam policy handle */
2178 
2179         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2180                                       pipe_hnd->desthost,
2181                                       MAXIMUM_ALLOWED_ACCESS,
2182                                       &connect_pol);
2183         if (!NT_STATUS_IS_OK(result)) {
2184                 goto done;
2185         }
2186 
2187         /* Get domain policy handle */
2188 
2189         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2190                                         &connect_pol,
2191                                         MAXIMUM_ALLOWED_ACCESS,
2192                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2193                                         &domain_pol);
2194         if (!NT_STATUS_IS_OK(result)) {
2195                 goto done;
2196         }
2197 
2198         /* Query domain groups */
2199         if (c->opt_long_list_entries)
2200                 d_printf("\nGroup name            Comment"
2201                          "\n-----------------------------\n");
2202         do {
2203                 uint32_t max_size, total_size, returned_size;
2204                 union samr_DispInfo info;
2205 
2206                 if (!global) break;
2207 
2208                 get_query_dispinfo_params(
2209                         loop_count, &max_entries, &max_size);
2210 
2211                 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2212                                                       &domain_pol,
2213                                                       3,
2214                                                       start_idx,
2215                                                       max_entries,
2216                                                       max_size,
2217                                                       &total_size,
2218                                                       &returned_size,
2219                                                       &info);
2220                 num_entries = info.info3.count;
2221                 start_idx += info.info3.count;
2222 
2223                 if (!NT_STATUS_IS_OK(result) &&
2224                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2225                         break;
2226 
2227                 for (i = 0; i < num_entries; i++) {
2228 
2229                         const char *group = NULL;
2230                         const char *desc = NULL;
2231 
2232                         group = info.info3.entries[i].account_name.string;
2233                         desc = info.info3.entries[i].description.string;
2234 
2235                         if (c->opt_long_list_entries)
2236                                 printf("%-21.21s %-50.50s\n",
2237                                        group, desc);
2238                         else
2239                                 printf("%s\n", group);
2240                 }
2241         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2242         /* query domain aliases */
2243         start_idx = 0;
2244         do {
2245                 if (!local) break;
2246 
2247                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2248                                                        &domain_pol,
2249                                                        &start_idx,
2250                                                        &groups,
2251                                                        0xffff,
2252                                                        &num_entries);
2253                 if (!NT_STATUS_IS_OK(result) &&
2254                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2255                         break;
2256 
2257                 for (i = 0; i < num_entries; i++) {
2258 
2259                         const char *description = NULL;
2260 
2261                         if (c->opt_long_list_entries) {
2262 
2263                                 struct policy_handle alias_pol;
2264                                 union samr_AliasInfo *info = NULL;
2265 
2266                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2267                                                                            &domain_pol,
2268                                                                            0x8,
2269                                                                            groups->entries[i].idx,
2270                                                                            &alias_pol))) &&
2271                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2272                                                                                 &alias_pol,
2273                                                                                 3,
2274                                                                                 &info))) &&
2275                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2276                                                                     &alias_pol)))) {
2277                                         description = info->description.string;
2278                                 }
2279                         }
2280 
2281                         if (description != NULL) {
2282                                 printf("%-21.21s %-50.50s\n",
2283                                        groups->entries[i].name.string,
2284                                        description);
2285                         } else {
2286                                 printf("%s\n", groups->entries[i].name.string);
2287                         }
2288                 }
2289         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2290         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2291         /* Get builtin policy handle */
2292 
2293         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2294                                         &connect_pol,
2295                                         MAXIMUM_ALLOWED_ACCESS,
2296                                         CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2297                                         &domain_pol);
2298         if (!NT_STATUS_IS_OK(result)) {
2299                 goto done;
2300         }
2301         /* query builtin aliases */
2302         start_idx = 0;
2303         do {
2304                 if (!builtin) break;
2305 
2306                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2307                                                        &domain_pol,
2308                                                        &start_idx,
2309                                                        &groups,
2310                                                        max_entries,
2311                                                        &num_entries);
2312                 if (!NT_STATUS_IS_OK(result) &&
2313                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2314                         break;
2315 
2316                 for (i = 0; i < num_entries; i++) {
2317 
2318                         const char *description = NULL;
2319 
2320                         if (c->opt_long_list_entries) {
2321 
2322                                 struct policy_handle alias_pol;
2323                                 union samr_AliasInfo *info = NULL;
2324 
2325                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2326                                                                            &domain_pol,
2327                                                                            0x8,
2328                                                                            groups->entries[i].idx,
2329                                                                            &alias_pol))) &&
2330                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2331                                                                                 &alias_pol,
2332                                                                                 3,
2333                                                                                 &info))) &&
2334                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2335                                                                     &alias_pol)))) {
2336                                         description = info->description.string;
2337                                 }
2338                         }
2339 
2340                         if (description != NULL) {
2341                                 printf("%-21.21s %-50.50s\n",
2342                                        groups->entries[i].name.string,
2343                                        description);
2344                         } else {
2345                                 printf("%s\n", groups->entries[i].name.string);
2346                         }
2347                 }
2348         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2349 
2350  done:
2351         return result;
2352 }
2353 
2354 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2355 {
2356         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2357                                rpc_group_list_internals,
2358                                argc, argv);
2359 }
2360 
2361 static NTSTATUS rpc_list_group_members(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
2362                                         struct rpc_pipe_client *pipe_hnd,
2363                                         TALLOC_CTX *mem_ctx,
2364                                         const char *domain_name,
2365                                         const DOM_SID *domain_sid,
2366                                         struct policy_handle *domain_pol,
2367                                         uint32 rid)
2368 {
2369         NTSTATUS result;
2370         struct policy_handle group_pol;
2371         uint32 num_members, *group_rids;
2372         int i;
2373         struct samr_RidTypeArray *rids = NULL;
2374         struct lsa_Strings names;
2375         struct samr_Ids types;
2376 
2377         fstring sid_str;
2378         sid_to_fstring(sid_str, domain_sid);
2379 
2380         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2381                                        domain_pol,
2382                                        MAXIMUM_ALLOWED_ACCESS,
2383                                        rid,
2384                                        &group_pol);
2385 
2386         if (!NT_STATUS_IS_OK(result))
2387                 return result;
2388 
2389         result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2390                                               &group_pol,
2391                                               &rids);
2392 
2393         if (!NT_STATUS_IS_OK(result))
2394                 return result;
2395 
2396         num_members = rids->count;
2397         group_rids = rids->rids;
2398 
2399         while (num_members > 0) {
2400                 int this_time = 512;
2401 
2402                 if (num_members < this_time)
2403                         this_time = num_members;
2404 
2405                 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2406                                                 domain_pol,
2407                                                 this_time,
2408                                                 group_rids,
2409                                                 &names,
2410                                                 &types);
2411 
2412                 if (!NT_STATUS_IS_OK(result))
2413                         return result;
2414 
2415                 /* We only have users as members, but make the output
2416                    the same as the output of alias members */
2417 
2418                 for (i = 0; i < this_time; i++) {
2419 
2420                         if (c->opt_long_list_entries) {
2421                                 printf("%s-%d %s\\%s %d\n", sid_str,
2422                                        group_rids[i], domain_name,
2423                                        names.names[i].string,
2424                                        SID_NAME_USER);
2425                         } else {
2426                                 printf("%s\\%s\n", domain_name,
2427                                         names.names[i].string);
2428                         }
2429                 }
2430 
2431                 num_members -= this_time;
2432                 group_rids += 512;
2433         }
2434 
2435         return NT_STATUS_OK;
2436 }
2437 
2438 static NTSTATUS rpc_list_alias_members(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
2439                                         struct rpc_pipe_client *pipe_hnd,
2440                                         TALLOC_CTX *mem_ctx,
2441                                         struct policy_handle *domain_pol,
2442                                         uint32 rid)
2443 {
2444         NTSTATUS result;
2445         struct rpc_pipe_client *lsa_pipe;
2446         struct policy_handle alias_pol, lsa_pol;
2447         uint32 num_members;
2448         DOM_SID *alias_sids;
2449         char **domains;
2450         char **names;
2451         enum lsa_SidType *types;
2452         int i;
2453         struct lsa_SidArray sid_array;
2454 
2455         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2456                                        domain_pol,
2457                                        MAXIMUM_ALLOWED_ACCESS,
2458                                        rid,
2459                                        &alias_pol);
2460 
2461         if (!NT_STATUS_IS_OK(result))
2462                 return result;
2463 
2464         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2465                                                &alias_pol,
2466                                                &sid_array);
2467 
2468         if (!NT_STATUS_IS_OK(result)) {
2469                 d_fprintf(stderr, "Couldn't list alias members\n");
2470                 return result;
2471         }
2472 
2473         num_members = sid_array.num_sids;
2474 
2475         if (num_members == 0) {
2476                 return NT_STATUS_OK;
2477         }
2478 
2479         result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2480                                           &ndr_table_lsarpc.syntax_id,
2481                                           &lsa_pipe);
2482         if (!NT_STATUS_IS_OK(result)) {
2483                 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
2484                         nt_errstr(result) );
2485                 return result;
2486         }
2487 
2488         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2489                                      SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2490 
2491         if (!NT_STATUS_IS_OK(result)) {
2492                 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
2493                 TALLOC_FREE(lsa_pipe);
2494                 return result;
2495         }
2496 
2497         alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
2498         if (!alias_sids) {
2499                 d_fprintf(stderr, "Out of memory\n");
2500                 TALLOC_FREE(lsa_pipe);
2501                 return NT_STATUS_NO_MEMORY;
2502         }
2503 
2504         for (i=0; i<num_members; i++) {
2505                 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2506         }
2507 
2508         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2509                                      num_members,  alias_sids,
2510                                      &domains, &names, &types);
2511 
2512         if (!NT_STATUS_IS_OK(result) &&
2513             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2514                 d_fprintf(stderr, "Couldn't lookup SIDs\n");
2515                 TALLOC_FREE(lsa_pipe);
2516                 return result;
2517         }
2518 
2519         for (i = 0; i < num_members; i++) {
2520                 fstring sid_str;
2521                 sid_to_fstring(sid_str, &alias_sids[i]);
2522 
2523                 if (c->opt_long_list_entries) {
2524                         printf("%s %s\\%s %d\n", sid_str,
2525                                domains[i] ? domains[i] : "*unknown*",
2526                                names[i] ? names[i] : "*unknown*", types[i]);
2527                 } else {
2528                         if (domains[i])
2529                                 printf("%s\\%s\n", domains[i], names[i]);
2530                         else
2531                                 printf("%s\n", sid_str);
2532                 }
2533         }
2534 
2535         TALLOC_FREE(lsa_pipe);
2536         return NT_STATUS_OK;
2537 }
2538 
2539 static NTSTATUS rpc_group_members_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
2540                                         const DOM_SID *domain_sid,
2541                                         const char *domain_name,
2542                                         struct cli_state *cli,
2543                                         struct rpc_pipe_client *pipe_hnd,
2544                                         TALLOC_CTX *mem_ctx,
2545                                         int argc,
2546                                         const char **argv)
2547 {
2548         NTSTATUS result;
2549         struct policy_handle connect_pol, domain_pol;
2550         struct samr_Ids rids, rid_types;
2551         struct lsa_String lsa_acct_name;
2552 
2553         /* Get sam policy handle */
2554 
2555         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2556                                       pipe_hnd->desthost,
2557                                       MAXIMUM_ALLOWED_ACCESS,
2558                                       &connect_pol);
2559 
2560         if (!NT_STATUS_IS_OK(result))
2561                 return result;
2562 
2563         /* Get domain policy handle */
2564 
2565         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2566                                         &connect_pol,
2567                                         MAXIMUM_ALLOWED_ACCESS,
2568                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2569                                         &domain_pol);
2570 
2571         if (!NT_STATUS_IS_OK(result))
2572                 return result;
2573 
2574         init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2575 
2576         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2577                                          &domain_pol,
2578                                          1,
2579                                          &lsa_acct_name,
2580                                          &rids,
2581                                          &rid_types);
2582 
2583         if (!NT_STATUS_IS_OK(result)) {
2584 
2585                 /* Ok, did not find it in the global sam, try with builtin */
2586 
2587                 DOM_SID sid_Builtin;
2588 
2589                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2590 
2591                 sid_copy(&sid_Builtin, &global_sid_Builtin);
2592 
2593                 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2594                                                 &connect_pol,
2595                                                 MAXIMUM_ALLOWED_ACCESS,
2596                                                 &sid_Builtin,
2597                                                 &domain_pol);
2598 
2599                 if (!NT_STATUS_IS_OK(result)) {
2600                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2601                         return result;
2602                 }
2603 
2604                 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2605                                                  &domain_pol,
2606                                                  1,
2607                                                  &lsa_acct_name,
2608                                                  &rids,
2609                                                  &rid_types);
2610 
2611                 if (!NT_STATUS_IS_OK(result)) {
2612                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2613                         return result;
2614                 }
2615         }
2616 
2617         if (rids.count != 1) {
2618                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2619                 return result;
2620         }
2621 
2622         if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2623                 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2624                                               domain_sid, &domain_pol,
2625                                               rids.ids[0]);
2626         }
2627 
2628         if (rid_types.ids[0] == SID_NAME_ALIAS) {
2629                 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
2630                                               rids.ids[0]);
2631         }
2632 
2633         return NT_STATUS_NO_SUCH_GROUP;
2634 }
2635 
2636 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2637 {
2638         if (argc != 1 || c->display_usage) {
2639                 return rpc_group_usage(c, argc, argv);
2640         }
2641 
2642         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2643                                rpc_group_members_internals,
2644                                argc, argv);
2645 }
2646 
2647 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2648 {
2649         NET_API_STATUS status;
2650         struct GROUP_INFO_0 g0;
2651         uint32_t parm_err;
2652 
2653         if (argc != 2) {
2654                 d_printf("Usage: 'net rpc group rename group newname'\n");
2655                 return -1;
2656         }
2657 
2658         g0.grpi0_name = argv[1];
2659 
2660         status = NetGroupSetInfo(c->opt_host,
2661                                  argv[0],
2662                                  0,
2663                                  (uint8_t *)&g0,
2664                                  &parm_err);
2665 
2666         if (status != 0) {
2667                 d_fprintf(stderr, "Renaming group %s failed with: %s\n",
2668                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
2669                         status));
2670                 return -1;
2671         }
2672 
2673         return 0;
2674 }
2675 
2676 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2677 {
2678         if (argc != 2 || c->display_usage) {
2679                 return rpc_group_usage(c, argc, argv);
2680         }
2681 
2682         return rpc_group_rename_internals(c, argc, argv);
2683 }
2684 
2685 /**
2686  * 'net rpc group' entrypoint.
2687  * @param argc  Standard main() style argc.
2688  * @param argv  Standard main() style argv. Initial components are already
2689  *              stripped.
2690  **/
2691 
2692 int net_rpc_group(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2693 {
2694         NET_API_STATUS status;
2695 
2696         struct functable func[] = {
2697                 {
2698                         "add",
2699                         rpc_group_add,
2700                         NET_TRANSPORT_RPC,
2701                         "Create specified group",
2702                         "net rpc group add\n"
2703                         "    Create specified group"
2704                 },
2705                 {
2706                         "delete",
2707                         rpc_group_delete,
2708                         NET_TRANSPORT_RPC,
2709                         "Delete specified group",
2710                         "net rpc group delete\n"
2711                         "    Delete specified group"
2712                 },
2713                 {
2714                         "addmem",
2715                         rpc_group_addmem,
2716                         NET_TRANSPORT_RPC,
2717                         "Add member to group",
2718                         "net rpc group addmem\n"
2719                         "    Add member to group"
2720                 },
2721                 {
2722                         "delmem",
2723                         rpc_group_delmem,
2724                         NET_TRANSPORT_RPC,
2725                         "Remove member from group",
2726                         "net rpc group delmem\n"
2727                         "    Remove member from group"
2728                 },
2729                 {
2730                         "list",
2731                         rpc_group_list,
2732                         NET_TRANSPORT_RPC,
2733                         "List groups",
2734                         "net rpc group list\n"
2735                         "    List groups"
2736                 },
2737                 {
2738                         "members",
2739                         rpc_group_members,
2740                         NET_TRANSPORT_RPC,
2741                         "List group members",
2742                         "net rpc group members\n"
2743                         "    List group members"
2744                 },
2745                 {
2746                         "rename",
2747                         rpc_group_rename,
2748                         NET_TRANSPORT_RPC,
2749                         "Rename group",
2750                         "net rpc group rename\n"
2751                         "    Rename group"
2752                 },
2753                 {NULL, NULL, 0, NULL, NULL}
2754         };
2755 
2756         status = libnetapi_init(&c->netapi_ctx);
2757         if (status != 0) {
2758                 return -1;
2759         }
2760         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
2761         libnetapi_set_password(c->netapi_ctx, c->opt_password);
2762         if (c->opt_kerberos) {
2763                 libnetapi_set_use_kerberos(c->netapi_ctx);
2764         }
2765 
2766         if (argc == 0) {
2767                 if (c->display_usage) {
2768                         d_printf("Usage:\n");
2769                         d_printf("net rpc group\n"
2770                                  "    Alias for net rpc group list global local "
2771                                  "builtin\n");
2772                         net_display_usage_from_functable(func);
2773                         return 0;
2774                 }
2775 
2776                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2777                                        rpc_group_list_internals,
2778                                        argc, argv);
2779         }
2780 
2781         return net_run_function(c, argc, argv, "net rpc group", func);
2782 }
2783 
2784 /****************************************************************************/
2785 
2786 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2787 {
2788         return net_share_usage(c, argc, argv);
2789 }
2790 
2791 /**
2792  * Add a share on a remote RPC server.
2793  *
2794  * @param argc  Standard main() style argc.
2795  * @param argv  Standard main() style argv. Initial components are already
2796  *              stripped.
2797  *
2798  * @return A shell status integer (0 for success).
2799  **/
2800 
2801 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2802 {
2803         NET_API_STATUS status;
2804         char *sharename;
2805         char *path;
2806         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
2807         uint32 num_users=0, perms=0;
2808         char *password=NULL; /* don't allow a share password */
2809         struct SHARE_INFO_2 i2;
2810         uint32_t parm_error = 0;
2811 
2812         if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
2813                 return rpc_share_usage(c, argc, argv);
2814         }
2815 
2816         if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
2817                 return -1;
2818         }
2819 
2820         path = strchr(sharename, '=');
2821         if (!path) {
2822                 return -1;
2823         }
2824 
2825         *path++ = '\0';
2826 
2827         i2.shi2_netname         = sharename;
2828         i2.shi2_type            = type;
2829         i2.shi2_remark          = c->opt_comment;
2830         i2.shi2_permissions     = perms;
2831         i2.shi2_max_uses        = c->opt_maxusers;
2832         i2.shi2_current_uses    = num_users;
2833         i2.shi2_path            = path;
2834         i2.shi2_passwd          = password;
2835 
2836         status = NetShareAdd(c->opt_host,
2837                              2,
2838                              (uint8_t *)&i2,
2839                              &parm_error);
2840         if (status != 0) {
2841                 printf("NetShareAdd failed with: %s\n",
2842                         libnetapi_get_error_string(c->netapi_ctx, status));
2843         }
2844 
2845         return status;
2846 }
2847 
2848 /**
2849  * Delete a share on a remote RPC server.
2850  *
2851  * @param domain_sid The domain sid acquired from the remote server.
2852  * @param argc  Standard main() style argc.
2853  * @param argv  Standard main() style argv. Initial components are already
2854  *              stripped.
2855  *
2856  * @return A shell status integer (0 for success).
2857  **/
2858 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2859 {
2860         if (argc < 1 || c->display_usage) {
2861                 return rpc_share_usage(c, argc, argv);
2862         }
2863 
2864         return NetShareDel(c->opt_host, argv[0], 0);
2865 }
2866 
2867 /**
2868  * Formatted print of share info
2869  *
2870  * @param r  pointer to SHARE_INFO_1 to format
2871  **/
2872 
2873 static void display_share_info_1(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
2874                                  struct SHARE_INFO_1 *r)
2875 {
2876         if (c->opt_long_list_entries) {
2877                 d_printf("%-12s %-8.8s %-50s\n",
2878                          r->shi1_netname,
2879                          net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
2880                          r->shi1_remark);
2881         } else {
2882                 d_printf("%s\n", r->shi1_netname);
2883         }
2884 }
2885 
2886 static WERROR get_share_info(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
2887                              struct rpc_pipe_client *pipe_hnd,
2888                              TALLOC_CTX *mem_ctx,
2889                              uint32 level,
2890                              int argc,
2891                              const char **argv,
2892                              struct srvsvc_NetShareInfoCtr *info_ctr)
2893 {
2894         WERROR result;
2895         NTSTATUS status;
2896         union srvsvc_NetShareInfo info;
2897 
2898         /* no specific share requested, enumerate all */
2899         if (argc == 0) {
2900 
2901                 uint32_t preferred_len = 0xffffffff;
2902                 uint32_t total_entries = 0;
2903                 uint32_t resume_handle = 0;
2904 
2905                 info_ctr->level = level;
2906 
2907                 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
2908                                                        pipe_hnd->desthost,
2909                                                        info_ctr,
2910                                                        preferred_len,
2911                                                        &total_entries,
2912                                                        &resume_handle,
2913                                                        &result);
2914                 return result;
2915         }
2916 
2917         /* request just one share */
2918         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
2919                                                pipe_hnd->desthost,
2920                                                argv[0],
2921                                                level,
2922                                                &info,
2923                                                &result);
2924 
2925         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
2926                 goto done;
2927         }
2928 
2929         /* construct ctr */
2930         ZERO_STRUCTP(info_ctr);
2931 
2932         info_ctr->level = level;
2933 
2934         switch (level) {
2935         case 1:
2936         {
2937                 struct srvsvc_NetShareCtr1 *ctr1;
2938 
2939                 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
2940                 W_ERROR_HAVE_NO_MEMORY(ctr1);
2941 
2942                 ctr1->count = 1;
2943                 ctr1->array = info.info1;
2944 
2945                 info_ctr->ctr.ctr1 = ctr1;
2946         }
2947         case 2:
2948         {
2949                 struct srvsvc_NetShareCtr2 *ctr2;
2950 
2951                 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
2952                 W_ERROR_HAVE_NO_MEMORY(ctr2);
2953 
2954                 ctr2->count = 1;
2955                 ctr2->array = info.info2;
2956 
2957                 info_ctr->ctr.ctr2 = ctr2;
2958         }
2959         case 502:
2960         {
2961                 struct srvsvc_NetShareCtr502 *ctr502;
2962 
2963                 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
2964                 W_ERROR_HAVE_NO_MEMORY(ctr502);
2965 
2966                 ctr502->count = 1;
2967                 ctr502->array = info.info502;
2968 
2969                 info_ctr->ctr.ctr502 = ctr502;
2970         }
2971         } /* switch */
2972 done:
2973         return result;
2974 }
2975 
2976 /***
2977  * 'net rpc share list' entrypoint.
2978  * @param argc  Standard main() style argc.
2979  * @param argv  Standard main() style argv. Initial components are already
2980  *              stripped.
2981  **/
2982 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
2983 {
2984         NET_API_STATUS status;
2985         struct SHARE_INFO_1 *i1 = NULL;
2986         uint32_t entries_read = 0;
2987         uint32_t total_entries = 0;
2988         uint32_t resume_handle = 0;
2989         uint32_t i, level = 1;
2990 
2991         if (c->display_usage) {
2992                 d_printf("Usage\n"
2993                          "net rpc share list\n"
2994                          "    List shares on remote server\n");
2995                 return 0;
2996         }
2997 
2998         status = NetShareEnum(c->opt_host,
2999                               level,
3000                               (uint8_t **)(void *)&i1,
3001                               (uint32_t)-1,
3002                               &entries_read,
3003                               &total_entries,
3004                               &resume_handle);
3005         if (status != 0) {
3006                 goto done;
3007         }
3008 
3009         /* Display results */
3010 
3011         if (c->opt_long_list_entries) {
3012                 d_printf(
3013         "\nEnumerating shared resources (exports) on remote server:\n\n"
3014         "\nShare name   Type     Description\n"
3015         "----------   ----     -----------\n");
3016         }
3017         for (i = 0; i < entries_read; i++)
3018                 display_share_info_1(c, &i1[i]);
3019  done:
3020         return status;
3021 }
3022 
3023 static bool check_share_availability(struct cli_state *cli, const char *netname)
     /* [<][>][^][v][top][bottom][index][help] */
3024 {
3025         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
3026                 d_printf("skipping   [%s]: not a file share.\n", netname);
3027                 return false;
3028         }
3029 
3030         if (!cli_tdis(cli))
3031                 return false;
3032 
3033         return true;
3034 }
3035 
3036 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
3037                                const char *netname, uint32 type)
3038 {
3039         /* only support disk shares */
3040         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3041                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3042                 return false;
3043         }
3044 
3045         /* skip builtin shares */
3046         /* FIXME: should print$ be added too ? */
3047         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3048             strequal(netname,"global"))
3049                 return false;
3050 
3051         if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3052                 printf("excluding  [%s]\n", netname);
3053                 return false;
3054         }
3055 
3056         return check_share_availability(cli, netname);
3057 }
3058 
3059 /**
3060  * Migrate shares from a remote RPC server to the local RPC server.
3061  *
3062  * All parameters are provided by the run_rpc_command function, except for
3063  * argc, argv which are passed through.
3064  *
3065  * @param domain_sid The domain sid acquired from the remote server.
3066  * @param cli A cli_state connected to the server.
3067  * @param mem_ctx Talloc context, destroyed on completion of the function.
3068  * @param argc  Standard main() style argc.
3069  * @param argv  Standard main() style argv. Initial components are already
3070  *              stripped.
3071  *
3072  * @return Normal NTSTATUS return.
3073  **/
3074 
3075 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
3076                                                 const DOM_SID *domain_sid,
3077                                                 const char *domain_name,
3078                                                 struct cli_state *cli,
3079                                                 struct rpc_pipe_client *pipe_hnd,
3080                                                 TALLOC_CTX *mem_ctx,
3081                                                 int argc,
3082                                                 const char **argv)
3083 {
3084         WERROR result;
3085         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3086         struct srvsvc_NetShareInfoCtr ctr_src;
3087         uint32 i;
3088         struct rpc_pipe_client *srvsvc_pipe = NULL;
3089         struct cli_state *cli_dst = NULL;
3090         uint32 level = 502; /* includes secdesc */
3091         uint32_t parm_error = 0;
3092 
3093         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3094                                 &ctr_src);
3095         if (!W_ERROR_IS_OK(result))
3096                 goto done;
3097 
3098         /* connect destination PI_SRVSVC */
3099         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3100                                      &ndr_table_srvsvc.syntax_id);
3101         if (!NT_STATUS_IS_OK(nt_status))
3102                 return nt_status;
3103 
3104 
3105         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3106 
3107                 union srvsvc_NetShareInfo info;
3108                 struct srvsvc_NetShareInfo502 info502 =
3109                         ctr_src.ctr.ctr502->array[i];
3110 
3111                 /* reset error-code */
3112                 nt_status = NT_STATUS_UNSUCCESSFUL;
3113 
3114                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3115                         continue;
3116 
3117                 /* finally add the share on the dst server */
3118 
3119                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
3120                         info502.name, info502.path, info502.comment);
3121 
3122                 info.info502 = &info502;
3123 
3124                 nt_status = rpccli_srvsvc_NetShareAdd(srvsvc_pipe, mem_ctx,
3125                                                       srvsvc_pipe->desthost,
3126                                                       502,
3127                                                       &info,
3128                                                       &parm_error,
3129                                                       &result);
3130 
3131                 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3132                         printf("           [%s] does already exist\n",
3133                                 info502.name);
3134                         continue;
3135                 }
3136 
3137                 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3138                         printf("cannot add share: %s\n", win_errstr(result));
3139                         goto done;
3140                 }
3141 
3142         }
3143 
3144         nt_status = NT_STATUS_OK;
3145 
3146 done:
3147         if (cli_dst) {
3148                 cli_shutdown(cli_dst);
3149         }
3150 
3151         return nt_status;
3152 
3153 }
3154 
3155 /**
3156  * Migrate shares from a RPC server to another.
3157  *
3158  * @param argc  Standard main() style argc.
3159  * @param argv  Standard main() style argv. Initial components are already
3160  *              stripped.
3161  *
3162  * @return A shell status integer (0 for success).
3163  **/
3164 static int rpc_share_migrate_shares(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
3165                                     const char **argv)
3166 {
3167         if (c->display_usage) {
3168                 d_printf("Usage:\n"
3169                          "net rpc share migrate shares\n"
3170                          "    Migrate shares to local server\n");
3171                 return 0;
3172         }
3173 
3174         if (!c->opt_host) {
3175                 printf("no server to migrate\n");
3176                 return -1;
3177         }
3178 
3179         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3180                                rpc_share_migrate_shares_internals,
3181                                argc, argv);
3182 }
3183 
3184 /**
3185  * Copy a file/dir
3186  *
3187  * @param f     file_info
3188  * @param mask  current search mask
3189  * @param state arg-pointer
3190  *
3191  **/
3192 static void copy_fn(const char *mnt, file_info *f,
     /* [<][>][^][v][top][bottom][index][help] */
3193                     const char *mask, void *state)
3194 {
3195         static NTSTATUS nt_status;
3196         static struct copy_clistate *local_state;
3197         static fstring filename, new_mask;
3198         fstring dir;
3199         char *old_dir;
3200         struct net_context *c;
3201 
3202         local_state = (struct copy_clistate *)state;
3203         nt_status = NT_STATUS_UNSUCCESSFUL;
3204 
3205         c = local_state->c;
3206 
3207         if (strequal(f->name, ".") || strequal(f->name, ".."))
3208                 return;
3209 
3210         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3211 
3212         /* DIRECTORY */
3213         if (f->mode & aDIR) {
3214 
3215                 DEBUG(3,("got dir: %s\n", f->name));
3216 
3217                 fstrcpy(dir, local_state->cwd);
3218                 fstrcat(dir, "\\");
3219                 fstrcat(dir, f->name);
3220 
3221                 switch (net_mode_share)
3222                 {
3223                 case NET_MODE_SHARE_MIGRATE:
3224                         /* create that directory */
3225                         nt_status = net_copy_file(c, local_state->mem_ctx,
3226                                                   local_state->cli_share_src,
3227                                                   local_state->cli_share_dst,
3228                                                   dir, dir,
3229                                                   c->opt_acls? true : false,
3230                                                   c->opt_attrs? true : false,
3231                                                   c->opt_timestamps? true:false,
3232                                                   false);
3233                         break;
3234                 default:
3235                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3236                         return;
3237                 }
3238 
3239                 if (!NT_STATUS_IS_OK(nt_status))
3240                         printf("could not handle dir %s: %s\n",
3241                                 dir, nt_errstr(nt_status));
3242 
3243                 /* search below that directory */
3244                 fstrcpy(new_mask, dir);
3245                 fstrcat(new_mask, "\\*");
3246 
3247                 old_dir = local_state->cwd;
3248                 local_state->cwd = dir;
3249                 if (!sync_files(local_state, new_mask))
3250                         printf("could not handle files\n");
3251                 local_state->cwd = old_dir;
3252 
3253                 return;
3254         }
3255 
3256 
3257         /* FILE */
3258         fstrcpy(filename, local_state->cwd);
3259         fstrcat(filename, "\\");
3260         fstrcat(filename, f->name);
3261 
3262         DEBUG(3,("got file: %s\n", filename));
3263 
3264         switch (net_mode_share)
3265         {
3266         case NET_MODE_SHARE_MIGRATE:
3267                 nt_status = net_copy_file(c, local_state->mem_ctx,
3268                                           local_state->cli_share_src,
3269                                           local_state->cli_share_dst,
3270                                           filename, filename,
3271                                           c->opt_acls? true : false,
3272                                           c->opt_attrs? true : false,
3273                                           c->opt_timestamps? true: false,
3274                                           true);
3275                 break;
3276         default:
3277                 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3278                 return;
3279         }
3280 
3281         if (!NT_STATUS_IS_OK(nt_status))
3282                 printf("could not handle file %s: %s\n",
3283                         filename, nt_errstr(nt_status));
3284 
3285 }
3286 
3287 /**
3288  * sync files, can be called recursivly to list files
3289  * and then call copy_fn for each file
3290  *
3291  * @param cp_clistate   pointer to the copy_clistate we work with
3292  * @param mask          the current search mask
3293  *
3294  * @return              Boolean result
3295  **/
3296 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
     /* [<][>][^][v][top][bottom][index][help] */
3297 {
3298         struct cli_state *targetcli;
3299         char *targetpath = NULL;
3300 
3301         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3302 
3303         if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src,
3304                                 mask, &targetcli, &targetpath ) ) {
3305                 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", 
3306                         mask, cli_errstr(cp_clistate->cli_share_src));
3307                 return false;
3308         }
3309 
3310         if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3311                 d_fprintf(stderr, "listing %s failed with error: %s\n",
3312                         mask, cli_errstr(targetcli));
3313                 return false;
3314         }
3315 
3316         return true;
3317 }
3318 
3319 
3320 /**
3321  * Set the top level directory permissions before we do any further copies.
3322  * Should set up ACL inheritance.
3323  **/
3324 
3325 bool copy_top_level_perms(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
3326                                 struct copy_clistate *cp_clistate,
3327                                 const char *sharename)
3328 {
3329         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3330 
3331         switch (net_mode_share) {
3332         case NET_MODE_SHARE_MIGRATE:
3333                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3334                 nt_status = net_copy_fileattr(c,
3335                                                 cp_clistate->mem_ctx,
3336                                                 cp_clistate->cli_share_src,
3337                                                 cp_clistate->cli_share_dst,
3338                                                 "\\", "\\",
3339                                                 c->opt_acls? true : false,
3340                                                 c->opt_attrs? true : false,
3341                                                 c->opt_timestamps? true: false,
3342                                                 false);
3343                 break;
3344         default:
3345                 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3346                 break;
3347         }
3348 
3349         if (!NT_STATUS_IS_OK(nt_status))  {
3350                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
3351                         sharename, nt_errstr(nt_status));
3352                 return false;
3353         }
3354 
3355         return true;
3356 }
3357 
3358 /**
3359  * Sync all files inside a remote share to another share (over smb).
3360  *
3361  * All parameters are provided by the run_rpc_command function, except for
3362  * argc, argv which are passed through.
3363  *
3364  * @param domain_sid The domain sid acquired from the remote server.
3365  * @param cli A cli_state connected to the server.
3366  * @param mem_ctx Talloc context, destroyed on completion of the function.
3367  * @param argc  Standard main() style argc.
3368  * @param argv  Standard main() style argv. Initial components are already
3369  *              stripped.
3370  *
3371  * @return Normal NTSTATUS return.
3372  **/
3373 
3374 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
3375                                                 const DOM_SID *domain_sid,
3376                                                 const char *domain_name,
3377                                                 struct cli_state *cli,
3378                                                 struct rpc_pipe_client *pipe_hnd,
3379                                                 TALLOC_CTX *mem_ctx,
3380                                                 int argc,
3381                                                 const char **argv)
3382 {
3383         WERROR result;
3384         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3385         struct srvsvc_NetShareInfoCtr ctr_src;
3386         uint32 i;
3387         uint32 level = 502;
3388         struct copy_clistate cp_clistate;
3389         bool got_src_share = false;
3390         bool got_dst_share = false;
3391         const char *mask = "\\*";
3392         char *dst = NULL;
3393 
3394         dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3395         if (dst == NULL) {
3396                 nt_status = NT_STATUS_NO_MEMORY;
3397                 goto done;
3398         }
3399 
3400         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3401                                 &ctr_src);
3402 
3403         if (!W_ERROR_IS_OK(result))
3404                 goto done;
3405 
3406         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3407 
3408                 struct srvsvc_NetShareInfo502 info502 =
3409                         ctr_src.ctr.ctr502->array[i];
3410 
3411                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3412                         continue;
3413 
3414                 /* one might not want to mirror whole discs :) */
3415                 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3416                         d_printf("skipping   [%s]: builtin/hidden share\n", info502.name);
3417                         continue;
3418                 }
3419 
3420                 switch (net_mode_share)
3421                 {
3422                 case NET_MODE_SHARE_MIGRATE:
3423                         printf("syncing");
3424                         break;
3425                 default:
3426                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3427                         break;
3428                 }
3429                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
3430                         info502.name,
3431                         c->opt_acls ? "including" : "without",
3432                         c->opt_attrs ? "including" : "without",
3433                         c->opt_timestamps ? "(preserving timestamps)" : "");
3434 
3435                 cp_clistate.mem_ctx = mem_ctx;
3436                 cp_clistate.cli_share_src = NULL;
3437                 cp_clistate.cli_share_dst = NULL;
3438                 cp_clistate.cwd = NULL;
3439                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3440                 cp_clistate.c = c;
3441 
3442                 /* open share source */
3443                 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3444                                                &cli->dest_ss, cli->desthost,
3445                                                info502.name, "A:");
3446                 if (!NT_STATUS_IS_OK(nt_status))
3447                         goto done;
3448 
3449                 got_src_share = true;
3450 
3451                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3452                         /* open share destination */
3453                         nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3454                                                        NULL, dst, info502.name, "A:");
3455                         if (!NT_STATUS_IS_OK(nt_status))
3456                                 goto done;
3457 
3458                         got_dst_share = true;
3459                 }
3460 
3461                 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3462                         d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", info502.name);
3463                         nt_status = NT_STATUS_UNSUCCESSFUL;
3464                         goto done;
3465                 }
3466 
3467                 if (!sync_files(&cp_clistate, mask)) {
3468                         d_fprintf(stderr, "could not handle files for share: %s\n", info502.name);
3469                         nt_status = NT_STATUS_UNSUCCESSFUL;
3470                         goto done;
3471                 }
3472         }
3473 
3474         nt_status = NT_STATUS_OK;
3475 
3476 done:
3477 
3478         if (got_src_share)
3479                 cli_shutdown(cp_clistate.cli_share_src);
3480 
3481         if (got_dst_share)
3482                 cli_shutdown(cp_clistate.cli_share_dst);
3483 
3484         SAFE_FREE(dst);
3485         return nt_status;
3486 
3487 }
3488 
3489 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
3490 {
3491         if (c->display_usage) {
3492                 d_printf("Usage:\n"
3493                          "net share migrate files\n"
3494                          "    Migrate files to local server\n");
3495                 return 0;
3496         }
3497 
3498         if (!c->opt_host) {
3499                 d_printf("no server to migrate\n");
3500                 return -1;
3501         }
3502 
3503         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3504                                rpc_share_migrate_files_internals,
3505                                argc, argv);
3506 }
3507 
3508 /**
3509  * Migrate share-ACLs from a remote RPC server to the local RPC server.
3510  *
3511  * All parameters are provided by the run_rpc_command function, except for
3512  * argc, argv which are passed through.
3513  *
3514  * @param domain_sid The domain sid acquired from the remote server.
3515  * @param cli A cli_state connected to the server.
3516  * @param mem_ctx Talloc context, destroyed on completion of the function.
3517  * @param argc  Standard main() style argc.
3518  * @param argv  Standard main() style argv. Initial components are already
3519  *              stripped.
3520  *
3521  * @return Normal NTSTATUS return.
3522  **/
3523 
3524 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
3525                                                 const DOM_SID *domain_sid,
3526                                                 const char *domain_name,
3527                                                 struct cli_state *cli,
3528                                                 struct rpc_pipe_client *pipe_hnd,
3529                                                 TALLOC_CTX *mem_ctx,
3530                                                 int argc,
3531                                                 const char **argv)
3532 {
3533         WERROR result;
3534         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3535         struct srvsvc_NetShareInfoCtr ctr_src;
3536         union srvsvc_NetShareInfo info;
3537         uint32 i;
3538         struct rpc_pipe_client *srvsvc_pipe = NULL;
3539         struct cli_state *cli_dst = NULL;
3540         uint32 level = 502; /* includes secdesc */
3541         uint32_t parm_error = 0;
3542 
3543         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3544                                 &ctr_src);
3545 
3546         if (!W_ERROR_IS_OK(result))
3547                 goto done;
3548 
3549         /* connect destination PI_SRVSVC */
3550         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3551                                      &ndr_table_srvsvc.syntax_id);
3552         if (!NT_STATUS_IS_OK(nt_status))
3553                 return nt_status;
3554 
3555 
3556         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3557 
3558                 struct srvsvc_NetShareInfo502 info502 =
3559                         ctr_src.ctr.ctr502->array[i];
3560 
3561                 /* reset error-code */
3562                 nt_status = NT_STATUS_UNSUCCESSFUL;
3563 
3564                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3565                         continue;
3566 
3567                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
3568                         info502.name, info502.path, info502.comment);
3569 
3570                 if (c->opt_verbose)
3571                         display_sec_desc(info502.sd_buf.sd);
3572 
3573                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3574                 info.info502 = &info502;
3575 
3576                 /* finally modify the share on the dst server */
3577                 nt_status = rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe, mem_ctx,
3578                                                           srvsvc_pipe->desthost,
3579                                                           info502.name,
3580                                                           level,
3581                                                           &info,
3582                                                           &parm_error,
3583                                                           &result);
3584                 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3585                         printf("cannot set share-acl: %s\n", win_errstr(result));
3586                         goto done;
3587                 }
3588 
3589         }
3590 
3591         nt_status = NT_STATUS_OK;
3592 
3593 done:
3594         if (cli_dst) {
3595                 cli_shutdown(cli_dst);
3596         }
3597 
3598         return nt_status;
3599 
3600 }
3601 
3602 /**
3603  * Migrate share-acls from a RPC server to another.
3604  *
3605  * @param argc  Standard main() style argc.
3606  * @param argv  Standard main() style argv. Initial components are already
3607  *              stripped.
3608  *
3609  * @return A shell status integer (0 for success).
3610  **/
3611 static int rpc_share_migrate_security(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
3612                                       const char **argv)
3613 {
3614         if (c->display_usage) {
3615                 d_printf("Usage:\n"
3616                          "net rpc share migrate security\n"
3617                          "    Migrate share-acls to local server\n");
3618                 return 0;
3619         }
3620 
3621         if (!c->opt_host) {
3622                 d_printf("no server to migrate\n");
3623                 return -1;
3624         }
3625 
3626         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3627                                rpc_share_migrate_security_internals,
3628                                argc, argv);
3629 }
3630 
3631 /**
3632  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3633  * from one server to another.
3634  *
3635  * @param argc  Standard main() style argc.
3636  * @param argv  Standard main() style argv. Initial components are already
3637  *              stripped.
3638  *
3639  * @return A shell status integer (0 for success).
3640  *
3641  **/
3642 static int rpc_share_migrate_all(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
3643                                  const char **argv)
3644 {
3645         int ret;
3646 
3647         if (c->display_usage) {
3648                 d_printf("Usage:\n"
3649                          "net rpc share migrate all\n"
3650                          "    Migrates shares including all share settings\n");
3651                 return 0;
3652         }
3653 
3654         if (!c->opt_host) {
3655                 d_printf("no server to migrate\n");
3656                 return -1;
3657         }
3658 
3659         /* order is important. we don't want to be locked out by the share-acl
3660          * before copying files - gd */
3661 
3662         ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3663                               rpc_share_migrate_shares_internals, argc, argv);
3664         if (ret)
3665                 return ret;
3666 
3667         ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3668                               rpc_share_migrate_files_internals, argc, argv);
3669         if (ret)
3670                 return ret;
3671 
3672         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3673                                rpc_share_migrate_security_internals, argc,
3674                                argv);
3675 }
3676 
3677 
3678 /**
3679  * 'net rpc share migrate' entrypoint.
3680  * @param argc  Standard main() style argc.
3681  * @param argv  Standard main() style argv. Initial components are already
3682  *              stripped.
3683  **/
3684 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
3685 {
3686 
3687         struct functable func[] = {
3688                 {
3689                         "all",
3690                         rpc_share_migrate_all,
3691                         NET_TRANSPORT_RPC,
3692                         "Migrate shares from remote to local server",
3693                         "net rpc share migrate all\n"
3694                         "    Migrate shares from remote to local server"
3695                 },
3696                 {
3697                         "files",
3698                         rpc_share_migrate_files,
3699                         NET_TRANSPORT_RPC,
3700                         "Migrate files from remote to local server",
3701                         "net rpc share migrate files\n"
3702                         "    Migrate files from remote to local server"
3703                 },
3704                 {
3705                         "security",
3706                         rpc_share_migrate_security,
3707                         NET_TRANSPORT_RPC,
3708                         "Migrate share-ACLs from remote to local server",
3709                         "net rpc share migrate security\n"
3710                         "    Migrate share-ACLs from remote to local server"
3711                 },
3712                 {
3713                         "shares",
3714                         rpc_share_migrate_shares,
3715                         NET_TRANSPORT_RPC,
3716                         "Migrate shares from remote to local server",
3717                         "net rpc share migrate shares\n"
3718                         "    Migrate shares from remote to local server"
3719                 },
3720                 {NULL, NULL, 0, NULL, NULL}
3721         };
3722 
3723         net_mode_share = NET_MODE_SHARE_MIGRATE;
3724 
3725         return net_run_function(c, argc, argv, "net rpc share migrate", func);
3726 }
3727 
3728 struct full_alias {
3729         DOM_SID sid;
3730         uint32 num_members;
3731         DOM_SID *members;
3732 };
3733 
3734 static int num_server_aliases;
3735 static struct full_alias *server_aliases;
3736 
3737 /*
3738  * Add an alias to the static list.
3739  */
3740 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
     /* [<][>][^][v][top][bottom][index][help] */
3741 {
3742         if (server_aliases == NULL)
3743                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3744 
3745         server_aliases[num_server_aliases] = *alias;
3746         num_server_aliases += 1;
3747 }
3748 
3749 /*
3750  * For a specific domain on the server, fetch all the aliases
3751  * and their members. Add all of them to the server_aliases.
3752  */
3753 
3754 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
3755                                         TALLOC_CTX *mem_ctx,
3756                                         struct policy_handle *connect_pol,
3757                                         const DOM_SID *domain_sid)
3758 {
3759         uint32 start_idx, max_entries, num_entries, i;
3760         struct samr_SamArray *groups = NULL;
3761         NTSTATUS result;
3762         struct policy_handle domain_pol;
3763 
3764         /* Get domain policy handle */
3765 
3766         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3767                                         connect_pol,
3768                                         MAXIMUM_ALLOWED_ACCESS,
3769                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
3770                                         &domain_pol);
3771         if (!NT_STATUS_IS_OK(result))
3772                 return result;
3773 
3774         start_idx = 0;
3775         max_entries = 250;
3776 
3777         do {
3778                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
3779                                                        &domain_pol,
3780                                                        &start_idx,
3781                                                        &groups,
3782                                                        max_entries,
3783                                                        &num_entries);
3784                 for (i = 0; i < num_entries; i++) {
3785 
3786                         struct policy_handle alias_pol;
3787                         struct full_alias alias;
3788                         struct lsa_SidArray sid_array;
3789                         int j;
3790 
3791                         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
3792                                                        &domain_pol,
3793                                                        MAXIMUM_ALLOWED_ACCESS,
3794                                                        groups->entries[i].idx,
3795                                                        &alias_pol);
3796                         if (!NT_STATUS_IS_OK(result))
3797                                 goto done;
3798 
3799                         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
3800                                                                &alias_pol,
3801                                                                &sid_array);
3802                         if (!NT_STATUS_IS_OK(result))
3803                                 goto done;
3804 
3805                         alias.num_members = sid_array.num_sids;
3806 
3807                         result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
3808                         if (!NT_STATUS_IS_OK(result))
3809                                 goto done;
3810 
3811                         alias.members = NULL;
3812 
3813                         if (alias.num_members > 0) {
3814                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3815 
3816                                 for (j = 0; j < alias.num_members; j++)
3817                                         sid_copy(&alias.members[j],
3818                                                  sid_array.sids[j].sid);
3819                         }
3820 
3821                         sid_copy(&alias.sid, domain_sid);
3822                         sid_append_rid(&alias.sid, groups->entries[i].idx);
3823 
3824                         push_alias(mem_ctx, &alias);
3825                 }
3826         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3827 
3828         result = NT_STATUS_OK;
3829 
3830  done:
3831         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
3832 
3833         return result;
3834 }
3835 
3836 /*
3837  * Dump server_aliases as names for debugging purposes.
3838  */
3839 
3840 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
3841                                 const DOM_SID *domain_sid,
3842                                 const char *domain_name,
3843                                 struct cli_state *cli,
3844                                 struct rpc_pipe_client *pipe_hnd,
3845                                 TALLOC_CTX *mem_ctx,
3846                                 int argc,
3847                                 const char **argv)
3848 {
3849         int i;
3850         NTSTATUS result;
3851         struct policy_handle lsa_pol;
3852 
3853         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
3854                                      SEC_FLAG_MAXIMUM_ALLOWED,
3855                                      &lsa_pol);
3856         if (!NT_STATUS_IS_OK(result))
3857                 return result;
3858 
3859         for (i=0; i<num_server_aliases; i++) {
3860                 char **names;
3861                 char **domains;
3862                 enum lsa_SidType *types;
3863                 int j;
3864 
3865                 struct full_alias *alias = &server_aliases[i];
3866 
3867                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
3868                                              &alias->sid,
3869                                              &domains, &names, &types);
3870                 if (!NT_STATUS_IS_OK(result))
3871                         continue;
3872 
3873                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
3874 
3875                 if (alias->num_members == 0) {
3876                         DEBUG(1, ("\n"));
3877                         continue;
3878                 }
3879 
3880                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
3881                                              alias->num_members,
3882                                              alias->members,
3883                                              &domains, &names, &types);
3884 
3885                 if (!NT_STATUS_IS_OK(result) &&
3886                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
3887                         continue;
3888 
3889                 for (j=0; j<alias->num_members; j++)
3890                         DEBUG(1, ("%s\\%s (%d); ",
3891                                   domains[j] ? domains[j] : "*unknown*", 
3892                                   names[j] ? names[j] : "*unknown*",types[j]));
3893                 DEBUG(1, ("\n"));
3894         }
3895 
3896         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
3897 
3898         return NT_STATUS_OK;
3899 }
3900 
3901 /*
3902  * Fetch a list of all server aliases and their members into
3903  * server_aliases.
3904  */
3905 
3906 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
3907                                         const DOM_SID *domain_sid,
3908                                         const char *domain_name,
3909                                         struct cli_state *cli,
3910                                         struct rpc_pipe_client *pipe_hnd,
3911                                         TALLOC_CTX *mem_ctx,
3912                                         int argc,
3913                                         const char **argv)
3914 {
3915         NTSTATUS result;
3916         struct policy_handle connect_pol;
3917 
3918         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
3919                                       pipe_hnd->desthost,
3920                                       MAXIMUM_ALLOWED_ACCESS,
3921                                       &connect_pol);
3922 
3923         if (!NT_STATUS_IS_OK(result))
3924                 goto done;
3925 
3926         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
3927                                           &global_sid_Builtin);
3928 
3929         if (!NT_STATUS_IS_OK(result))
3930                 goto done;
3931 
3932         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
3933                                           domain_sid);
3934 
3935         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
3936  done:
3937         return result;
3938 }
3939 
3940 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
     /* [<][>][^][v][top][bottom][index][help] */
3941 {
3942         token->num_sids = 4;
3943 
3944         if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
3945                 d_fprintf(stderr, "malloc failed\n");
3946                 token->num_sids = 0;
3947                 return;
3948         }
3949 
3950         token->user_sids[0] = *user_sid;
3951         sid_copy(&token->user_sids[1], &global_sid_World);
3952         sid_copy(&token->user_sids[2], &global_sid_Network);
3953         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
3954 }
3955 
3956 static void free_user_token(NT_USER_TOKEN *token)
     /* [<][>][^][v][top][bottom][index][help] */
3957 {
3958         SAFE_FREE(token->user_sids);
3959 }
3960 
3961 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
3962 {
3963         if (is_sid_in_token(token, sid))
3964                 return;
3965 
3966         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
3967         if (!token->user_sids) {
3968                 return;
3969         }
3970 
3971         sid_copy(&token->user_sids[token->num_sids], sid);
3972 
3973         token->num_sids += 1;
3974 }
3975 
3976 struct user_token {
3977         fstring name;
3978         NT_USER_TOKEN token;
3979 };
3980 
3981 static void dump_user_token(struct user_token *token)
     /* [<][>][^][v][top][bottom][index][help] */
3982 {
3983         int i;
3984 
3985         d_printf("%s\n", token->name);
3986 
3987         for (i=0; i<token->token.num_sids; i++) {
3988                 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
3989         }
3990 }
3991 
3992 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
     /* [<][>][^][v][top][bottom][index][help] */
3993 {
3994         int i;
3995 
3996         for (i=0; i<alias->num_members; i++) {
3997                 if (sid_compare(sid, &alias->members[i]) == 0)
3998                         return true;
3999         }
4000 
4001         return false;
4002 }
4003 
4004 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
     /* [<][>][^][v][top][bottom][index][help] */
4005 {
4006         int i;
4007 
4008         for (i=0; i<num_server_aliases; i++) {
4009                 if (is_alias_member(&sid, &server_aliases[i]))
4010                         add_sid_to_token(token, &server_aliases[i].sid);
4011         }
4012 }
4013 
4014 /*
4015  * We got a user token with all the SIDs we can know about without asking the
4016  * server directly. These are the user and domain group sids. All of these can
4017  * be members of aliases. So scan the list of aliases for each of the SIDs and
4018  * add them to the token.
4019  */
4020 
4021 static void collect_alias_memberships(NT_USER_TOKEN *token)
     /* [<][>][^][v][top][bottom][index][help] */
4022 {
4023         int num_global_sids = token->num_sids;
4024         int i;
4025 
4026         for (i=0; i<num_global_sids; i++) {
4027                 collect_sid_memberships(token, token->user_sids[i]);
4028         }
4029 }
4030 
4031 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
     /* [<][>][^][v][top][bottom][index][help] */
4032 {
4033         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4034         enum wbcSidType type;
4035         fstring full_name;
4036         struct wbcDomainSid wsid;
4037         char *sid_str = NULL;
4038         DOM_SID user_sid;
4039         uint32_t num_groups;
4040         gid_t *groups = NULL;
4041         uint32_t i;
4042 
4043         fstr_sprintf(full_name, "%s%c%s",
4044                      domain, *lp_winbind_separator(), user);
4045 
4046         /* First let's find out the user sid */
4047 
4048         wbc_status = wbcLookupName(domain, user, &wsid, &type);
4049 
4050         if (!WBC_ERROR_IS_OK(wbc_status)) {
4051                 DEBUG(1, ("winbind could not find %s: %s\n",
4052                           full_name, wbcErrorString(wbc_status)));
4053                 return false;
4054         }
4055 
4056         wbc_status = wbcSidToString(&wsid, &sid_str);
4057         if (!WBC_ERROR_IS_OK(wbc_status)) {
4058                 return false;
4059         }
4060 
4061         if (type != SID_NAME_USER) {
4062                 wbcFreeMemory(sid_str);
4063                 DEBUG(1, ("%s is not a user\n", full_name));
4064                 return false;
4065         }
4066 
4067         if (!string_to_sid(&user_sid, sid_str)) {
4068                 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4069                 return false;
4070         }
4071 
4072         wbcFreeMemory(sid_str);
4073         sid_str = NULL;
4074 
4075         init_user_token(token, &user_sid);
4076 
4077         /* And now the groups winbind knows about */
4078 
4079         wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4080         if (!WBC_ERROR_IS_OK(wbc_status)) {
4081                 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4082                         full_name, wbcErrorString(wbc_status)));
4083                 return false;
4084         }
4085 
4086         for (i = 0; i < num_groups; i++) {
4087                 gid_t gid = groups[i];
4088                 DOM_SID sid;
4089 
4090                 wbc_status = wbcGidToSid(gid, &wsid);
4091                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4092                         DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4093                                   (unsigned int)gid, wbcErrorString(wbc_status)));
4094                         wbcFreeMemory(groups);
4095                         return false;
4096                 }
4097 
4098                 wbc_status = wbcSidToString(&wsid, &sid_str);
4099                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4100                         wbcFreeMemory(groups);
4101                         return false;
4102                 }
4103 
4104                 DEBUG(3, (" %s\n", sid_str));
4105 
4106                 string_to_sid(&sid, sid_str);
4107                 wbcFreeMemory(sid_str);
4108                 sid_str = NULL;
4109 
4110                 add_sid_to_token(token, &sid);
4111         }
4112         wbcFreeMemory(groups);
4113 
4114         return true;
4115 }
4116 
4117 /**
4118  * Get a list of all user tokens we want to look at
4119  **/
4120 
4121 static bool get_user_tokens(struct net_context *c, int *num_tokens,
     /* [<][>][^][v][top][bottom][index][help] */
4122                             struct user_token **user_tokens)
4123 {
4124         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4125         uint32_t i, num_users;
4126         const char **users;
4127         struct user_token *result;
4128         TALLOC_CTX *frame = NULL;
4129 
4130         if (lp_winbind_use_default_domain() &&
4131             (c->opt_target_workgroup == NULL)) {
4132                 d_fprintf(stderr, "winbind use default domain = yes set, "
4133                          "please specify a workgroup\n");
4134                 return false;
4135         }
4136 
4137         /* Send request to winbind daemon */
4138 
4139         wbc_status = wbcListUsers(NULL, &num_users, &users);
4140         if (!WBC_ERROR_IS_OK(wbc_status)) {
4141                 DEBUG(1, ("winbind could not list users: %s\n",
4142                           wbcErrorString(wbc_status)));
4143                 return false;
4144         }
4145 
4146         result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4147 
4148         if (result == NULL) {
4149                 DEBUG(1, ("Could not malloc sid array\n"));
4150                 wbcFreeMemory(users);
4151                 return false;
4152         }
4153 
4154         frame = talloc_stackframe();
4155         for (i=0; i < num_users; i++) {
4156                 fstring domain, user;
4157                 char *p;
4158 
4159                 fstrcpy(result[i].name, users[i]);
4160 
4161                 p = strchr(users[i], *lp_winbind_separator());
4162 
4163                 DEBUG(3, ("%s\n", users[i]));
4164 
4165                 if (p == NULL) {
4166                         fstrcpy(domain, c->opt_target_workgroup);
4167                         fstrcpy(user, users[i]);
4168                 } else {
4169                         *p++ = '\0';
4170                         fstrcpy(domain, users[i]);
4171                         strupper_m(domain);
4172                         fstrcpy(user, p);
4173                 }
4174 
4175                 get_user_sids(domain, user, &(result[i].token));
4176                 i+=1;
4177         }
4178         TALLOC_FREE(frame);
4179         wbcFreeMemory(users);
4180 
4181         *num_tokens = num_users;
4182         *user_tokens = result;
4183 
4184         return true;
4185 }
4186 
4187 static bool get_user_tokens_from_file(FILE *f,
     /* [<][>][^][v][top][bottom][index][help] */
4188                                       int *num_tokens,
4189                                       struct user_token **tokens)
4190 {
4191         struct user_token *token = NULL;
4192 
4193         while (!feof(f)) {
4194                 fstring line;
4195 
4196                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4197                         return true;
4198                 }
4199 
4200                 if (line[strlen(line)-1] == '\n')
4201                         line[strlen(line)-1] = '\0';
4202 
4203                 if (line[0] == ' ') {
4204                         /* We have a SID */
4205 
4206                         DOM_SID sid;
4207                         if(!string_to_sid(&sid, &line[1])) {
4208                                 DEBUG(1,("get_user_tokens_from_file: Could "
4209                                         "not convert sid %s \n",&line[1]));
4210                                 return false;
4211                         }
4212 
4213                         if (token == NULL) {
4214                                 DEBUG(0, ("File does not begin with username"));
4215                                 return false;
4216                         }
4217 
4218                         add_sid_to_token(&token->token, &sid);
4219                         continue;
4220                 }
4221 
4222                 /* And a new user... */
4223 
4224                 *num_tokens += 1;
4225                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4226                 if (*tokens == NULL) {
4227                         DEBUG(0, ("Could not realloc tokens\n"));
4228                         return false;
4229                 }
4230 
4231                 token = &((*tokens)[*num_tokens-1]);
4232 
4233                 fstrcpy(token->name, line);
4234                 token->token.num_sids = 0;
4235                 token->token.user_sids = NULL;
4236                 continue;
4237         }
4238         
4239         return false;
4240 }
4241 
4242 
4243 /*
4244  * Show the list of all users that have access to a share
4245  */
4246 
4247 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
4248                         TALLOC_CTX *mem_ctx,
4249                         const char *netname,
4250                         int num_tokens,
4251                         struct user_token *tokens)
4252 {
4253         int fnum;
4254         SEC_DESC *share_sd = NULL;
4255         SEC_DESC *root_sd = NULL;
4256         struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4257         int i;
4258         union srvsvc_NetShareInfo info;
4259         WERROR result;
4260         NTSTATUS status;
4261         uint16 cnum;
4262 
4263         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4264                                                pipe_hnd->desthost,
4265                                                netname,
4266                                                502,
4267                                                &info,
4268                                                &result);
4269 
4270         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4271                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4272                           netname));
4273                 return;
4274         }
4275 
4276         share_sd = info.info502->sd_buf.sd;
4277         if (share_sd == NULL) {
4278                 DEBUG(1, ("Got no secdesc for share %s\n",
4279                           netname));
4280         }
4281 
4282         cnum = cli->cnum;
4283 
4284         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
4285                 return;
4286         }
4287 
4288         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4289 
4290         if (fnum != -1) {
4291                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4292         }
4293 
4294         for (i=0; i<num_tokens; i++) {
4295                 uint32 acc_granted;
4296 
4297                 if (share_sd != NULL) {
4298                         status = se_access_check(share_sd, &tokens[i].token,
4299                                              1, &acc_granted);
4300 
4301                         if (!NT_STATUS_IS_OK(status)) {
4302                                 DEBUG(1, ("Could not check share_sd for "
4303                                           "user %s\n",
4304                                           tokens[i].name));
4305                                 continue;
4306                         }
4307                 }
4308 
4309                 if (root_sd == NULL) {
4310                         d_printf(" %s\n", tokens[i].name);
4311                         continue;
4312                 }
4313 
4314                 status = se_access_check(root_sd, &tokens[i].token,
4315                                      1, &acc_granted);
4316                 if (!NT_STATUS_IS_OK(status)) {
4317                         DEBUG(1, ("Could not check root_sd for user %s\n",
4318                                   tokens[i].name));
4319                         continue;
4320                 }
4321                 d_printf(" %s\n", tokens[i].name);
4322         }
4323 
4324         if (fnum != -1)
4325                 cli_close(cli, fnum);
4326         cli_tdis(cli);
4327         cli->cnum = cnum;
4328         
4329         return;
4330 }
4331 
4332 struct share_list {
4333         int num_shares;
4334         char **shares;
4335 };
4336 
4337 static void collect_share(const char *name, uint32 m,
     /* [<][>][^][v][top][bottom][index][help] */
4338                           const char *comment, void *state)
4339 {
4340         struct share_list *share_list = (struct share_list *)state;
4341 
4342         if (m != STYPE_DISKTREE)
4343                 return;
4344 
4345         share_list->num_shares += 1;
4346         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4347         if (!share_list->shares) {
4348                 share_list->num_shares = 0;
4349                 return;
4350         }
4351         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4352 }
4353 
4354 /**
4355  * List shares on a remote RPC server, including the security descriptors.
4356  *
4357  * All parameters are provided by the run_rpc_command function, except for
4358  * argc, argv which are passed through.
4359  *
4360  * @param domain_sid The domain sid acquired from the remote server.
4361  * @param cli A cli_state connected to the server.
4362  * @param mem_ctx Talloc context, destroyed on completion of the function.
4363  * @param argc  Standard main() style argc.
4364  * @param argv  Standard main() style argv. Initial components are already
4365  *              stripped.
4366  *
4367  * @return Normal NTSTATUS return.
4368  **/
4369 
4370 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4371                                                 const DOM_SID *domain_sid,
4372                                                 const char *domain_name,
4373                                                 struct cli_state *cli,
4374                                                 struct rpc_pipe_client *pipe_hnd,
4375                                                 TALLOC_CTX *mem_ctx,
4376                                                 int argc,
4377                                                 const char **argv)
4378 {
4379         int ret;
4380         bool r;
4381         uint32 i;
4382         FILE *f;
4383 
4384         struct user_token *tokens = NULL;
4385         int num_tokens = 0;
4386 
4387         struct share_list share_list;
4388 
4389         if (argc == 0) {
4390                 f = stdin;
4391         } else {
4392                 f = fopen(argv[0], "r");
4393         }
4394 
4395         if (f == NULL) {
4396                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4397                 return NT_STATUS_UNSUCCESSFUL;
4398         }
4399 
4400         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4401 
4402         if (f != stdin)
4403                 fclose(f);
4404 
4405         if (!r) {
4406                 DEBUG(0, ("Could not read users from file\n"));
4407                 return NT_STATUS_UNSUCCESSFUL;
4408         }
4409 
4410         for (i=0; i<num_tokens; i++)
4411                 collect_alias_memberships(&tokens[i].token);
4412 
4413         share_list.num_shares = 0;
4414         share_list.shares = NULL;
4415 
4416         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4417 
4418         if (ret == -1) {
4419                 DEBUG(0, ("Error returning browse list: %s\n",
4420                           cli_errstr(cli)));
4421                 goto done;
4422         }
4423 
4424         for (i = 0; i < share_list.num_shares; i++) {
4425                 char *netname = share_list.shares[i];
4426 
4427                 if (netname[strlen(netname)-1] == '$')
4428                         continue;
4429 
4430                 d_printf("%s\n", netname);
4431 
4432                 show_userlist(pipe_hnd, mem_ctx, netname,
4433                               num_tokens, tokens);
4434         }
4435  done:
4436         for (i=0; i<num_tokens; i++) {
4437                 free_user_token(&tokens[i].token);
4438         }
4439         SAFE_FREE(tokens);
4440         SAFE_FREE(share_list.shares);
4441 
4442         return NT_STATUS_OK;
4443 }
4444 
4445 static int rpc_share_allowedusers(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
4446                                   const char **argv)
4447 {
4448         int result;
4449 
4450         if (c->display_usage) {
4451                 d_printf("Usage:\n"
4452                          "net rpc share allowedusers\n"
4453                          "    List allowed users\n");
4454                 return 0;
4455         }
4456 
4457         result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4458                                  rpc_aliaslist_internals,
4459                                  argc, argv);
4460         if (result != 0)
4461                 return result;
4462 
4463         result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4464                                  rpc_aliaslist_dump,
4465                                  argc, argv);
4466         if (result != 0)
4467                 return result;
4468 
4469         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4470                                rpc_share_allowedusers_internals,
4471                                argc, argv);
4472 }
4473 
4474 int net_usersidlist(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
4475 {
4476         int num_tokens = 0;
4477         struct user_token *tokens = NULL;
4478         int i;
4479 
4480         if (argc != 0) {
4481                 net_usersidlist_usage(c, argc, argv);
4482                 return 0;
4483         }
4484 
4485         if (!get_user_tokens(c, &num_tokens, &tokens)) {
4486                 DEBUG(0, ("Could not get the user/sid list\n"));
4487                 return 0;
4488         }
4489 
4490         for (i=0; i<num_tokens; i++) {
4491                 dump_user_token(&tokens[i]);
4492                 free_user_token(&tokens[i].token);
4493         }
4494 
4495         SAFE_FREE(tokens);
4496         return 1;
4497 }
4498 
4499 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
4500 {
4501         d_printf("net usersidlist\n"
4502                  "\tprints out a list of all users the running winbind knows\n"
4503                  "\tabout, together with all their SIDs. This is used as\n"
4504                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
4505 
4506         net_common_flags_usage(c, argc, argv);
4507         return -1;
4508 }
4509 
4510 /**
4511  * 'net rpc share' entrypoint.
4512  * @param argc  Standard main() style argc.
4513  * @param argv  Standard main() style argv. Initial components are already
4514  *              stripped.
4515  **/
4516 
4517 int net_rpc_share(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
4518 {
4519         NET_API_STATUS status;
4520 
4521         struct functable func[] = {
4522                 {
4523                         "add",
4524                         rpc_share_add,
4525                         NET_TRANSPORT_RPC,
4526                         "Add share",
4527                         "net rpc share add\n"
4528                         "    Add share"
4529                 },
4530                 {
4531                         "delete",
4532                         rpc_share_delete,
4533                         NET_TRANSPORT_RPC,
4534                         "Remove share",
4535                         "net rpc share delete\n"
4536                         "    Remove share"
4537                 },
4538                 {
4539                         "allowedusers",
4540                         rpc_share_allowedusers,
4541                         NET_TRANSPORT_RPC,
4542                         "Modify allowed users",
4543                         "net rpc share allowedusers\n"
4544                         "    Modify allowed users"
4545                 },
4546                 {
4547                         "migrate",
4548                         rpc_share_migrate,
4549                         NET_TRANSPORT_RPC,
4550                         "Migrate share to local server",
4551                         "net rpc share migrate\n"
4552                         "    Migrate share to local server"
4553                 },
4554                 {
4555                         "list",
4556                         rpc_share_list,
4557                         NET_TRANSPORT_RPC,
4558                         "List shares",
4559                         "net rpc share list\n"
4560                         "    List shares"
4561                 },
4562                 {NULL, NULL, 0, NULL, NULL}
4563         };
4564 
4565         status = libnetapi_init(&c->netapi_ctx);
4566         if (status != 0) {
4567                 return -1;
4568         }
4569         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4570         libnetapi_set_password(c->netapi_ctx, c->opt_password);
4571         if (c->opt_kerberos) {
4572                 libnetapi_set_use_kerberos(c->netapi_ctx);
4573         }
4574 
4575         if (argc == 0) {
4576                 if (c->display_usage) {
4577                         d_printf("Usage:\n"
4578                                  "net rpc share\n"
4579                                  "    List shares\n"
4580                                  "    Alias for net rpc share list\n");
4581                         net_display_usage_from_functable(func);
4582                         return 0;
4583                 }
4584 
4585                 return rpc_share_list(c, argc, argv);
4586         }
4587 
4588         return net_run_function(c, argc, argv, "net rpc share", func);
4589 }
4590 
4591 static NTSTATUS rpc_sh_share_list(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4592                                   TALLOC_CTX *mem_ctx,
4593                                   struct rpc_sh_ctx *ctx,
4594                                   struct rpc_pipe_client *pipe_hnd,
4595                                   int argc, const char **argv)
4596 {
4597 
4598         return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
4599 }
4600 
4601 static NTSTATUS rpc_sh_share_add(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4602                                  TALLOC_CTX *mem_ctx,
4603                                  struct rpc_sh_ctx *ctx,
4604                                  struct rpc_pipe_client *pipe_hnd,
4605                                  int argc, const char **argv)
4606 {
4607         NET_API_STATUS status;
4608         uint32_t parm_err = 0;
4609         struct SHARE_INFO_2 i2;
4610 
4611         if ((argc < 2) || (argc > 3)) {
4612                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
4613                           ctx->whoami);
4614                 return NT_STATUS_INVALID_PARAMETER;
4615         }
4616 
4617         i2.shi2_netname         = argv[0];
4618         i2.shi2_type            = STYPE_DISKTREE;
4619         i2.shi2_remark          = (argc == 3) ? argv[2] : "";
4620         i2.shi2_permissions     = 0;
4621         i2.shi2_max_uses        = 0;
4622         i2.shi2_current_uses    = 0;
4623         i2.shi2_path            = argv[1];
4624         i2.shi2_passwd          = NULL;
4625 
4626         status = NetShareAdd(pipe_hnd->desthost,
4627                              2,
4628                              (uint8_t *)&i2,
4629                              &parm_err);
4630 
4631         return werror_to_ntstatus(W_ERROR(status));
4632 }
4633 
4634 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4635                                     TALLOC_CTX *mem_ctx,
4636                                     struct rpc_sh_ctx *ctx,
4637                                     struct rpc_pipe_client *pipe_hnd,
4638                                     int argc, const char **argv)
4639 {
4640         if (argc != 1) {
4641                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4642                 return NT_STATUS_INVALID_PARAMETER;
4643         }
4644 
4645         return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
4646 }
4647 
4648 static NTSTATUS rpc_sh_share_info(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4649                                   TALLOC_CTX *mem_ctx,
4650                                   struct rpc_sh_ctx *ctx,
4651                                   struct rpc_pipe_client *pipe_hnd,
4652                                   int argc, const char **argv)
4653 {
4654         union srvsvc_NetShareInfo info;
4655         WERROR result;
4656         NTSTATUS status;
4657 
4658         if (argc != 1) {
4659                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4660                 return NT_STATUS_INVALID_PARAMETER;
4661         }
4662 
4663         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4664                                                pipe_hnd->desthost,
4665                                                argv[0],
4666                                                2,
4667                                                &info,
4668                                                &result);
4669         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4670                 goto done;
4671         }
4672 
4673         d_printf("Name:     %s\n", info.info2->name);
4674         d_printf("Comment:  %s\n", info.info2->comment);
4675         d_printf("Path:     %s\n", info.info2->path);
4676         d_printf("Password: %s\n", info.info2->password);
4677 
4678  done:
4679         return werror_to_ntstatus(result);
4680 }
4681 
4682 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4683                                       struct rpc_sh_ctx *ctx)
4684 {
4685         static struct rpc_sh_cmd cmds[] = {
4686 
4687         { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
4688           "List available shares" },
4689 
4690         { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
4691           "Add a share" },
4692 
4693         { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
4694           "Delete a share" },
4695 
4696         { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
4697           "Get information about a share" },
4698 
4699         { NULL, NULL, 0, NULL, NULL }
4700         };
4701 
4702         return cmds;
4703 }
4704 
4705 /****************************************************************************/
4706 
4707 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
4708 {
4709         return net_file_usage(c, argc, argv);
4710 }
4711 
4712 /**
4713  * Close a file on a remote RPC server.
4714  *
4715  * @param argc  Standard main() style argc.
4716  * @param argv  Standard main() style argv. Initial components are already
4717  *              stripped.
4718  *
4719  * @return A shell status integer (0 for success).
4720  **/
4721 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
4722 {
4723         if (argc < 1 || c->display_usage) {
4724                 return rpc_file_usage(c, argc, argv);
4725         }
4726 
4727         return NetFileClose(c->opt_host, atoi(argv[0]));
4728 }
4729 
4730 /**
4731  * Formatted print of open file info
4732  *
4733  * @param r  struct FILE_INFO_3 contents
4734  **/
4735 
4736 static void display_file_info_3(struct FILE_INFO_3 *r)
     /* [<][>][^][v][top][bottom][index][help] */
4737 {
4738         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4739                  r->fi3_id, r->fi3_username, r->fi3_permissions,
4740                  r->fi3_num_locks, r->fi3_pathname);
4741 }
4742 
4743 /**
4744  * List files for a user on a remote RPC server.
4745  *
4746  * @param argc  Standard main() style argc.
4747  * @param argv  Standard main() style argv. Initial components are already
4748  *              stripped.
4749  *
4750  * @return A shell status integer (0 for success)..
4751  **/
4752 
4753 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
4754 {
4755         NET_API_STATUS status;
4756         uint32 preferred_len = 0xffffffff, i;
4757         const char *username=NULL;
4758         uint32_t total_entries = 0;
4759         uint32_t entries_read = 0;
4760         uint32_t resume_handle = 0;
4761         struct FILE_INFO_3 *i3 = NULL;
4762 
4763         if (c->display_usage) {
4764                 return rpc_file_usage(c, argc, argv);
4765         }
4766 
4767         /* if argc > 0, must be user command */
4768         if (argc > 0) {
4769                 username = smb_xstrdup(argv[0]);
4770         }
4771 
4772         status = NetFileEnum(c->opt_host,
4773                              NULL,
4774                              username,
4775                              3,
4776                              (uint8_t **)(void *)&i3,
4777                              preferred_len,
4778                              &entries_read,
4779                              &total_entries,
4780                              &resume_handle);
4781 
4782         if (status != 0) {
4783                 goto done;
4784         }
4785 
4786         /* Display results */
4787 
4788         d_printf(
4789                  "\nEnumerating open files on remote server:\n\n"
4790                  "\nFileId  Opened by            Perms  Locks  Path"
4791                  "\n------  ---------            -----  -----  ---- \n");
4792         for (i = 0; i < entries_read; i++) {
4793                 display_file_info_3(&i3[i]);
4794         }
4795  done:
4796         return status;
4797 }
4798 
4799 /**
4800  * 'net rpc file' entrypoint.
4801  * @param argc  Standard main() style argc.
4802  * @param argv  Standard main() style argv. Initial components are already
4803  *              stripped.
4804  **/
4805 
4806 int net_rpc_file(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
4807 {
4808         NET_API_STATUS status;
4809 
4810         struct functable func[] = {
4811                 {
4812                         "close",
4813                         rpc_file_close,
4814                         NET_TRANSPORT_RPC,
4815                         "Close opened file",
4816                         "net rpc file close\n"
4817                         "    Close opened file"
4818                 },
4819                 {
4820                         "user",
4821                         rpc_file_user,
4822                         NET_TRANSPORT_RPC,
4823                         "List files opened by user",
4824                         "net rpc file user\n"
4825                         "    List files opened by user"
4826                 },
4827 #if 0
4828                 {
4829                         "info",
4830                         rpc_file_info,
4831                         NET_TRANSPORT_RPC,
4832                         "Display information about opened file",
4833                         "net rpc file info\n"
4834                         "    Display information about opened file"
4835                 },
4836 #endif
4837                 {NULL, NULL, 0, NULL, NULL}
4838         };
4839 
4840         status = libnetapi_init(&c->netapi_ctx);
4841         if (status != 0) {
4842                 return -1;
4843         }
4844         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4845         libnetapi_set_password(c->netapi_ctx, c->opt_password);
4846         if (c->opt_kerberos) {
4847                 libnetapi_set_use_kerberos(c->netapi_ctx);
4848         }
4849 
4850         if (argc == 0) {
4851                 if (c->display_usage) {
4852                         d_printf("Usage:\n");
4853                         d_printf("net rpc file\n"
4854                                  "    List opened files\n");
4855                         net_display_usage_from_functable(func);
4856                         return 0;
4857                 }
4858 
4859                 return rpc_file_user(c, argc, argv);
4860         }
4861 
4862         return net_run_function(c, argc, argv, "net rpc file", func);
4863 }
4864 
4865 /**
4866  * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
4867  *
4868  * All parameters are provided by the run_rpc_command function, except for
4869  * argc, argv which are passed through.
4870  *
4871  * @param c     A net_context structure.
4872  * @param domain_sid The domain sid acquired from the remote server.
4873  * @param cli A cli_state connected to the server.
4874  * @param mem_ctx Talloc context, destroyed on completion of the function.
4875  * @param argc  Standard main() style argc.
4876  * @param argv  Standard main() style argv. Initial components are already
4877  *              stripped.
4878  *
4879  * @return Normal NTSTATUS return.
4880  **/
4881 
4882 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4883                                         const DOM_SID *domain_sid,
4884                                         const char *domain_name,
4885                                         struct cli_state *cli,
4886                                         struct rpc_pipe_client *pipe_hnd,
4887                                         TALLOC_CTX *mem_ctx,
4888                                         int argc,
4889                                         const char **argv)
4890 {
4891         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4892 
4893         result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
4894 
4895         if (NT_STATUS_IS_OK(result)) {
4896                 d_printf("\nShutdown successfully aborted\n");
4897                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
4898         } else
4899                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
4900 
4901         return result;
4902 }
4903 
4904 /**
4905  * ABORT the shutdown of a remote RPC Server, over winreg pipe.
4906  *
4907  * All parameters are provided by the run_rpc_command function, except for
4908  * argc, argv which are passed through.
4909  *
4910  * @param c     A net_context structure.
4911  * @param domain_sid The domain sid acquired from the remote server.
4912  * @param cli A cli_state connected to the server.
4913  * @param mem_ctx Talloc context, destroyed on completion of the function.
4914  * @param argc  Standard main() style argc.
4915  * @param argv  Standard main() style argv. Initial components are already
4916  *              stripped.
4917  *
4918  * @return Normal NTSTATUS return.
4919  **/
4920 
4921 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4922                                                 const DOM_SID *domain_sid,
4923                                                 const char *domain_name,
4924                                                 struct cli_state *cli,
4925                                                 struct rpc_pipe_client *pipe_hnd,
4926                                                 TALLOC_CTX *mem_ctx,
4927                                                 int argc,
4928                                                 const char **argv)
4929 {
4930         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4931 
4932         result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
4933 
4934         if (NT_STATUS_IS_OK(result)) {
4935                 d_printf("\nShutdown successfully aborted\n");
4936                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
4937         } else
4938                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
4939 
4940         return result;
4941 }
4942 
4943 /**
4944  * ABORT the shutdown of a remote RPC server.
4945  *
4946  * @param argc  Standard main() style argc.
4947  * @param argv  Standard main() style argv. Initial components are already
4948  *              stripped.
4949  *
4950  * @return A shell status integer (0 for success).
4951  **/
4952 
4953 static int rpc_shutdown_abort(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
4954                               const char **argv)
4955 {
4956         int rc = -1;
4957 
4958         if (c->display_usage) {
4959                 d_printf("Usage:\n"
4960                          "net rpc abortshutdown\n"
4961                          "    Abort a scheduled shutdown\n");
4962                 return 0;
4963         }
4964 
4965         rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
4966                              rpc_shutdown_abort_internals, argc, argv);
4967 
4968         if (rc == 0)
4969                 return rc;
4970 
4971         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4972 
4973         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
4974                                rpc_reg_shutdown_abort_internals,
4975                                argc, argv);
4976 }
4977 
4978 /**
4979  * Shut down a remote RPC Server via initshutdown pipe.
4980  *
4981  * All parameters are provided by the run_rpc_command function, except for
4982  * argc, argv which are passed through.
4983  *
4984  * @param c     A net_context structure.
4985  * @param domain_sid The domain sid acquired from the remote server.
4986  * @param cli A cli_state connected to the server.
4987  * @param mem_ctx Talloc context, destroyed on completion of the function.
4988  * @param argc  Standard main() style argc.
4989  * @param argv  Standard main() style argv. Initial components are already
4990  *              stripped.
4991  *
4992  * @return Normal NTSTATUS return.
4993  **/
4994 
4995 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
4996                                      const DOM_SID *domain_sid,
4997                                      const char *domain_name,
4998                                      struct cli_state *cli,
4999                                      struct rpc_pipe_client *pipe_hnd,
5000                                      TALLOC_CTX *mem_ctx,
5001                                      int argc,
5002                                      const char **argv)
5003 {
5004         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5005         const char *msg = "This machine will be shutdown shortly";
5006         uint32 timeout = 20;
5007         struct lsa_StringLarge msg_string;
5008 
5009         if (c->opt_comment) {
5010                 msg = c->opt_comment;
5011         }
5012         if (c->opt_timeout) {
5013                 timeout = c->opt_timeout;
5014         }
5015 
5016         msg_string.string = msg;
5017 
5018         /* create an entry */
5019         result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5020                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5021                         NULL);
5022 
5023         if (NT_STATUS_IS_OK(result)) {
5024                 d_printf("\nShutdown of remote machine succeeded\n");
5025                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5026         } else {
5027                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5028         }
5029         return result;
5030 }
5031 
5032 /**
5033  * Shut down a remote RPC Server via winreg pipe.
5034  *
5035  * All parameters are provided by the run_rpc_command function, except for
5036  * argc, argv which are passed through.
5037  *
5038  * @param c     A net_context structure.
5039  * @param domain_sid The domain sid acquired from the remote server.
5040  * @param cli A cli_state connected to the server.
5041  * @param mem_ctx Talloc context, destroyed on completion of the function.
5042  * @param argc  Standard main() style argc.
5043  * @param argv  Standard main() style argv. Initial components are already
5044  *              stripped.
5045  *
5046  * @return Normal NTSTATUS return.
5047  **/
5048 
5049 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
5050                                     const DOM_SID *domain_sid,
5051                                     const char *domain_name,
5052                                     struct cli_state *cli,
5053                                     struct rpc_pipe_client *pipe_hnd,
5054                                     TALLOC_CTX *mem_ctx,
5055                                     int argc,
5056                                     const char **argv)
5057 {
5058         const char *msg = "This machine will be shutdown shortly";
5059         uint32 timeout = 20;
5060         struct lsa_StringLarge msg_string;
5061         NTSTATUS result;
5062         WERROR werr;
5063 
5064         if (c->opt_comment) {
5065                 msg = c->opt_comment;
5066         }
5067         msg_string.string = msg;
5068 
5069         if (c->opt_timeout) {
5070                 timeout = c->opt_timeout;
5071         }
5072 
5073         /* create an entry */
5074         result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5075                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5076                         &werr);
5077 
5078         if (NT_STATUS_IS_OK(result)) {
5079                 d_printf("\nShutdown of remote machine succeeded\n");
5080         } else {
5081                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5082                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5083                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5084                 else
5085                         d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5086         }
5087 
5088         return result;
5089 }
5090 
5091 /**
5092  * Shut down a remote RPC server.
5093  *
5094  * @param argc  Standard main() style argc.
5095  * @param argv  Standard main() style argv. Initial components are already
5096  *              stripped.
5097  *
5098  * @return A shell status integer (0 for success).
5099  **/
5100 
5101 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
5102 {
5103         int rc =  -1;
5104 
5105         if (c->display_usage) {
5106                 d_printf("Usage:\n"
5107                          "net rpc shutdown\n"
5108                          "    Shut down a remote RPC server\n");
5109                 return 0;
5110         }
5111 
5112         rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5113                              rpc_init_shutdown_internals, argc, argv);
5114 
5115         if (rc) {
5116                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5117                 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5118                                      rpc_reg_shutdown_internals, argc, argv);
5119         }
5120 
5121         return rc;
5122 }
5123 
5124 /***************************************************************************
5125   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5126  ***************************************************************************/
5127 
5128 /**
5129  * Add interdomain trust account to the RPC server.
5130  * All parameters (except for argc and argv) are passed by run_rpc_command
5131  * function.
5132  *
5133  * @param c     A net_context structure.
5134  * @param domain_sid The domain sid acquired from the server.
5135  * @param cli A cli_state connected to the server.
5136  * @param mem_ctx Talloc context, destroyed on completion of the function.
5137  * @param argc  Standard main() style argc.
5138  * @param argv  Standard main() style argv. Initial components are already
5139  *              stripped.
5140  *
5141  * @return normal NTSTATUS return code.
5142  */
5143 
5144 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
5145                                                 const DOM_SID *domain_sid,
5146                                                 const char *domain_name,
5147                                                 struct cli_state *cli,
5148                                                 struct rpc_pipe_client *pipe_hnd,
5149                                                 TALLOC_CTX *mem_ctx,
5150                                                 int argc,
5151                                                 const char **argv)
5152 {
5153         struct policy_handle connect_pol, domain_pol, user_pol;
5154         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5155         char *acct_name;
5156         struct lsa_String lsa_acct_name;
5157         uint32 acb_info;
5158         uint32 acct_flags=0;
5159         uint32 user_rid;
5160         uint32_t access_granted = 0;
5161         union samr_UserInfo info;
5162         unsigned int orig_timeout;
5163 
5164         if (argc != 2) {
5165                 d_printf("Usage: net rpc trustdom add <domain_name> "
5166                          "<trust password>\n");
5167                 return NT_STATUS_INVALID_PARAMETER;
5168         }
5169 
5170         /* 
5171          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5172          */
5173 
5174         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5175                 return NT_STATUS_NO_MEMORY;
5176         }
5177 
5178         strupper_m(acct_name);
5179 
5180         init_lsa_String(&lsa_acct_name, acct_name);
5181 
5182         /* Get samr policy handle */
5183         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5184                                       pipe_hnd->desthost,
5185                                       MAXIMUM_ALLOWED_ACCESS,
5186                                       &connect_pol);
5187         if (!NT_STATUS_IS_OK(result)) {
5188                 goto done;
5189         }
5190 
5191         /* Get domain policy handle */
5192         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5193                                         &connect_pol,
5194                                         MAXIMUM_ALLOWED_ACCESS,
5195                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5196                                         &domain_pol);
5197         if (!NT_STATUS_IS_OK(result)) {
5198                 goto done;
5199         }
5200 
5201         /* This call can take a long time - allow the server to time out.
5202          * 35 seconds should do it. */
5203 
5204         orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5205 
5206         /* Create trusting domain's account */
5207         acb_info = ACB_NORMAL;
5208         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5209                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5210                      SAMR_USER_ACCESS_SET_PASSWORD |
5211                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5212                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5213 
5214         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5215                                          &domain_pol,
5216                                          &lsa_acct_name,
5217                                          acb_info,
5218                                          acct_flags,
5219                                          &user_pol,
5220                                          &access_granted,
5221                                          &user_rid);
5222 
5223         /* And restore our original timeout. */
5224         rpccli_set_timeout(pipe_hnd, orig_timeout);
5225 
5226         if (!NT_STATUS_IS_OK(result)) {
5227                 d_printf("net rpc trustdom add: create user %s failed %s\n",
5228                         acct_name, nt_errstr(result));
5229                 goto done;
5230         }
5231 
5232         {
5233                 struct samr_CryptPassword crypt_pwd;
5234 
5235                 ZERO_STRUCT(info.info23);
5236 
5237                 init_samr_CryptPassword(argv[1],
5238                                         &cli->user_session_key,
5239                                         &crypt_pwd);
5240 
5241                 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5242                                                   SAMR_FIELD_NT_PASSWORD_PRESENT;
5243                 info.info23.info.acct_flags = ACB_DOMTRUST;
5244                 info.info23.password = crypt_pwd;
5245 
5246                 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5247                                                   &user_pol,
5248                                                   23,
5249                                                   &info);
5250 
5251                 if (!NT_STATUS_IS_OK(result)) {
5252                         DEBUG(0,("Could not set trust account password: %s\n",
5253                                  nt_errstr(result)));
5254                         goto done;
5255                 }
5256         }
5257 
5258  done:
5259         SAFE_FREE(acct_name);
5260         return result;
5261 }
5262 
5263 /**
5264  * Create interdomain trust account for a remote domain.
5265  *
5266  * @param argc Standard argc.
5267  * @param argv Standard argv without initial components.
5268  *
5269  * @return Integer status (0 means success).
5270  **/
5271 
5272 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
5273 {
5274         if (argc > 0 && !c->display_usage) {
5275                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5276                                        rpc_trustdom_add_internals, argc, argv);
5277         } else {
5278                 d_printf("Usage:\n"
5279                         "net rpc trustdom add <domain_name> <trust password>\n");
5280                 return -1;
5281         }
5282 }
5283 
5284 
5285 /**
5286  * Remove interdomain trust account from the RPC server.
5287  * All parameters (except for argc and argv) are passed by run_rpc_command
5288  * function.
5289  *
5290  * @param c     A net_context structure.
5291  * @param domain_sid The domain sid acquired from the server.
5292  * @param cli A cli_state connected to the server.
5293  * @param mem_ctx Talloc context, destroyed on completion of the function.
5294  * @param argc  Standard main() style argc.
5295  * @param argv  Standard main() style argv. Initial components are already
5296  *              stripped.
5297  *
5298  * @return normal NTSTATUS return code.
5299  */
5300 
5301 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
5302                                         const DOM_SID *domain_sid,
5303                                         const char *domain_name,
5304                                         struct cli_state *cli,
5305                                         struct rpc_pipe_client *pipe_hnd,
5306                                         TALLOC_CTX *mem_ctx,
5307                                         int argc,
5308                                         const char **argv)
5309 {
5310         struct policy_handle connect_pol, domain_pol, user_pol;
5311         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5312         char *acct_name;
5313         DOM_SID trust_acct_sid;
5314         struct samr_Ids user_rids, name_types;
5315         struct lsa_String lsa_acct_name;
5316 
5317         if (argc != 1) {
5318                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5319                 return NT_STATUS_INVALID_PARAMETER;
5320         }
5321 
5322         /*
5323          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5324          */
5325         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5326 
5327         if (acct_name == NULL)
5328                 return NT_STATUS_NO_MEMORY;
5329 
5330         strupper_m(acct_name);
5331 
5332         /* Get samr policy handle */
5333         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5334                                       pipe_hnd->desthost,
5335                                       MAXIMUM_ALLOWED_ACCESS,
5336                                       &connect_pol);
5337         if (!NT_STATUS_IS_OK(result)) {
5338                 goto done;
5339         }
5340 
5341         /* Get domain policy handle */
5342         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5343                                         &connect_pol,
5344                                         MAXIMUM_ALLOWED_ACCESS,
5345                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5346                                         &domain_pol);
5347         if (!NT_STATUS_IS_OK(result)) {
5348                 goto done;
5349         }
5350 
5351         init_lsa_String(&lsa_acct_name, acct_name);
5352 
5353         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5354                                          &domain_pol,
5355                                          1,
5356                                          &lsa_acct_name,
5357                                          &user_rids,
5358                                          &name_types);
5359 
5360         if (!NT_STATUS_IS_OK(result)) {
5361                 d_printf("net rpc trustdom del: LookupNames on user %s failed %s\n",
5362                         acct_name, nt_errstr(result) );
5363                 goto done;
5364         }
5365 
5366         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5367                                       &domain_pol,
5368                                       MAXIMUM_ALLOWED_ACCESS,
5369                                       user_rids.ids[0],
5370                                       &user_pol);
5371 
5372         if (!NT_STATUS_IS_OK(result)) {
5373                 d_printf("net rpc trustdom del: OpenUser on user %s failed %s\n",
5374                         acct_name, nt_errstr(result) );
5375                 goto done;
5376         }
5377 
5378         /* append the rid to the domain sid */
5379         sid_copy(&trust_acct_sid, domain_sid);
5380         if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5381                 goto done;
5382         }
5383 
5384         /* remove the sid */
5385 
5386         result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5387                                                            &user_pol,
5388                                                            &trust_acct_sid);
5389         if (!NT_STATUS_IS_OK(result)) {
5390                 d_printf("net rpc trustdom del: RemoveMemberFromForeignDomain on user %s failed %s\n",
5391                         acct_name, nt_errstr(result) );
5392                 goto done;
5393         }
5394 
5395         /* Delete user */
5396 
5397         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5398                                         &user_pol);
5399 
5400         if (!NT_STATUS_IS_OK(result)) {
5401                 d_printf("net rpc trustdom del: DeleteUser on user %s failed %s\n",
5402                         acct_name, nt_errstr(result) );
5403                 goto done;
5404         }
5405 
5406         if (!NT_STATUS_IS_OK(result)) {
5407                 d_printf("Could not set trust account password: %s\n",
5408                    nt_errstr(result));
5409                 goto done;
5410         }
5411 
5412  done:
5413         return result;
5414 }
5415 
5416 /**
5417  * Delete interdomain trust account for a remote domain.
5418  *
5419  * @param argc Standard argc.
5420  * @param argv Standard argv without initial components.
5421  *
5422  * @return Integer status (0 means success).
5423  **/
5424 
5425 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
5426 {
5427         if (argc > 0 && !c->display_usage) {
5428                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5429                                        rpc_trustdom_del_internals, argc, argv);
5430         } else {
5431                 d_printf("Usage:\n"
5432                          "net rpc trustdom del <domain>\n");
5433                 return -1;
5434         }
5435 }
5436 
5437 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
5438                                      struct cli_state *cli,
5439                                      TALLOC_CTX *mem_ctx,
5440                                      const char *domain_name)
5441 {
5442         char *dc_name = NULL;
5443         const char *buffer = NULL;
5444         struct rpc_pipe_client *netr;
5445         NTSTATUS status;
5446 
5447         /* Use NetServerEnum2 */
5448 
5449         if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5450                 SAFE_FREE(dc_name);
5451                 return NT_STATUS_OK;
5452         }
5453 
5454         DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5455                  for domain %s\n", domain_name));
5456 
5457         /* Try netr_GetDcName */
5458 
5459         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5460                                           &netr);
5461         if (!NT_STATUS_IS_OK(status)) {
5462                 return status;
5463         }
5464 
5465         status = rpccli_netr_GetDcName(netr, mem_ctx,
5466                                        cli->desthost,
5467                                        domain_name,
5468                                        &buffer,
5469                                        NULL);
5470         TALLOC_FREE(netr);
5471 
5472         if (NT_STATUS_IS_OK(status)) {
5473                 return status;
5474         }
5475 
5476         DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5477                  for domain %s\n", domain_name));
5478 
5479         return status;
5480 }
5481 
5482 /**
5483  * Establish trust relationship to a trusting domain.
5484  * Interdomain account must already be created on remote PDC.
5485  *
5486  * @param c    A net_context structure.
5487  * @param argc Standard argc.
5488  * @param argv Standard argv without initial components.
5489  *
5490  * @return Integer status (0 means success).
5491  **/
5492 
5493 static int rpc_trustdom_establish(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
5494                                   const char **argv)
5495 {
5496         struct cli_state *cli = NULL;
5497         struct sockaddr_storage server_ss;
5498         struct rpc_pipe_client *pipe_hnd = NULL;
5499         struct policy_handle connect_hnd;
5500         TALLOC_CTX *mem_ctx;
5501         NTSTATUS nt_status;
5502         DOM_SID *domain_sid;
5503 
5504         char* domain_name;
5505         char* acct_name;
5506         fstring pdc_name;
5507         union lsa_PolicyInformation *info = NULL;
5508 
5509         /*
5510          * Connect to \\server\ipc$ as 'our domain' account with password
5511          */
5512 
5513         if (argc != 1 || c->display_usage) {
5514                 d_printf("Usage:\n"
5515                          "net rpc trustdom establish <domain_name>\n");
5516                 return -1;
5517         }
5518 
5519         domain_name = smb_xstrdup(argv[0]);
5520         strupper_m(domain_name);
5521 
5522         /* account name used at first is our domain's name with '$' */
5523         if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
5524                 return -1;
5525         }
5526         strupper_m(acct_name);
5527 
5528         /*
5529          * opt_workgroup will be used by connection functions further,
5530          * hence it should be set to remote domain name instead of ours
5531          */
5532         if (c->opt_workgroup) {
5533                 c->opt_workgroup = smb_xstrdup(domain_name);
5534         };
5535 
5536         c->opt_user_name = acct_name;
5537 
5538         /* find the domain controller */
5539         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5540                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5541                 return -1;
5542         }
5543 
5544         /* connect to ipc$ as username/password */
5545         nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
5546         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5547 
5548                 /* Is it trusting domain account for sure ? */
5549                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5550                         nt_errstr(nt_status)));
5551                 return -1;
5552         }
5553 
5554         /* store who we connected to */
5555 
5556         saf_store( domain_name, pdc_name );
5557 
5558         /*
5559          * Connect to \\server\ipc$ again (this time anonymously)
5560          */
5561 
5562         nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
5563                                              (char*)pdc_name);
5564 
5565         if (NT_STATUS_IS_ERR(nt_status)) {
5566                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5567                         domain_name, nt_errstr(nt_status)));
5568                 return -1;
5569         }
5570 
5571         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5572                                     "domain %s", domain_name))) {
5573                 DEBUG(0, ("talloc_init() failed\n"));
5574                 cli_shutdown(cli);
5575                 return -1;
5576         }
5577 
5578         /* Make sure we're talking to a proper server */
5579 
5580         nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
5581         if (!NT_STATUS_IS_OK(nt_status)) {
5582                 cli_shutdown(cli);
5583                 talloc_destroy(mem_ctx);
5584                 return -1;
5585         }
5586 
5587         /*
5588          * Call LsaOpenPolicy and LsaQueryInfo
5589          */
5590 
5591         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5592                                              &pipe_hnd);
5593         if (!NT_STATUS_IS_OK(nt_status)) {
5594                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5595                 cli_shutdown(cli);
5596                 talloc_destroy(mem_ctx);
5597                 return -1;
5598         }
5599 
5600         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
5601                                          &connect_hnd);
5602         if (NT_STATUS_IS_ERR(nt_status)) {
5603                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5604                         nt_errstr(nt_status)));
5605                 cli_shutdown(cli);
5606                 talloc_destroy(mem_ctx);
5607                 return -1;
5608         }
5609 
5610         /* Querying info level 5 */
5611 
5612         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5613                                                &connect_hnd,
5614                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5615                                                &info);
5616         if (NT_STATUS_IS_ERR(nt_status)) {
5617                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5618                         nt_errstr(nt_status)));
5619                 cli_shutdown(cli);
5620                 talloc_destroy(mem_ctx);
5621                 return -1;
5622         }
5623 
5624         domain_sid = info->account_domain.sid;
5625 
5626         /* There should be actually query info level 3 (following nt serv behaviour),
5627            but I still don't know if it's _really_ necessary */
5628 
5629         /*
5630          * Store the password in secrets db
5631          */
5632 
5633         if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
5634                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5635                 cli_shutdown(cli);
5636                 talloc_destroy(mem_ctx);
5637                 return -1;
5638         }
5639 
5640         /*
5641          * Close the pipes and clean up
5642          */
5643 
5644         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5645         if (NT_STATUS_IS_ERR(nt_status)) {
5646                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5647                         nt_errstr(nt_status)));
5648                 cli_shutdown(cli);
5649                 talloc_destroy(mem_ctx);
5650                 return -1;
5651         }
5652 
5653         cli_shutdown(cli);
5654 
5655         talloc_destroy(mem_ctx);
5656 
5657         d_printf("Trust to domain %s established\n", domain_name);
5658         return 0;
5659 }
5660 
5661 /**
5662  * Revoke trust relationship to the remote domain.
5663  *
5664  * @param c    A net_context structure.
5665  * @param argc Standard argc.
5666  * @param argv Standard argv without initial components.
5667  *
5668  * @return Integer status (0 means success).
5669  **/
5670 
5671 static int rpc_trustdom_revoke(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
5672                                const char **argv)
5673 {
5674         char* domain_name;
5675         int rc = -1;
5676 
5677         if (argc < 1 || c->display_usage) {
5678                 d_printf("Usage:\n"
5679                          "net rpc trustdom revoke <domain_name>\n"
5680                          "  Revoke trust relationship\n"
5681                          "    domain_name\tName of domain to revoke trust\n");
5682                 return -1;
5683         }
5684 
5685         /* generate upper cased domain name */
5686         domain_name = smb_xstrdup(argv[0]);
5687         strupper_m(domain_name);
5688 
5689         /* delete password of the trust */
5690         if (!pdb_del_trusteddom_pw(domain_name)) {
5691                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5692                           domain_name));
5693                 goto done;
5694         };
5695 
5696         rc = 0;
5697 done:
5698         SAFE_FREE(domain_name);
5699         return rc;
5700 }
5701 
5702 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
5703                                         const DOM_SID *domain_sid,
5704                                         const char *domain_name,
5705                                         struct cli_state *cli,
5706                                         struct rpc_pipe_client *pipe_hnd,
5707                                         TALLOC_CTX *mem_ctx,
5708                                         int argc,
5709                                         const char **argv)
5710 {
5711         fstring str_sid;
5712         sid_to_fstring(str_sid, domain_sid);
5713         d_printf("%s\n", str_sid);
5714         return NT_STATUS_OK;
5715 }
5716 
5717 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
     /* [<][>][^][v][top][bottom][index][help] */
5718 {
5719         fstring ascii_sid, padding;
5720         int pad_len, col_len = 20;
5721 
5722         /* convert sid into ascii string */
5723         sid_to_fstring(ascii_sid, dom_sid);
5724 
5725         /* calculate padding space for d_printf to look nicer */
5726         pad_len = col_len - strlen(trusted_dom_name);
5727         padding[pad_len] = 0;
5728         do padding[--pad_len] = ' '; while (pad_len);
5729 
5730         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
5731 }
5732 
5733 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
5734                                       TALLOC_CTX *mem_ctx,
5735                                       struct policy_handle *pol,
5736                                       DOM_SID dom_sid,
5737                                       const char *trusted_dom_name)
5738 {
5739         NTSTATUS nt_status;
5740         union lsa_TrustedDomainInfo *info = NULL;
5741         char *cleartextpwd = NULL;
5742         uint8_t nt_hash[16];
5743         DATA_BLOB data = data_blob_null;
5744 
5745         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
5746                                                            pol,
5747                                                            &dom_sid,
5748                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
5749                                                            &info);
5750         if (NT_STATUS_IS_ERR(nt_status)) {
5751                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5752                 nt_errstr(nt_status)));
5753                 goto done;
5754         }
5755 
5756         data = data_blob(info->password.password->data,
5757                          info->password.password->length);
5758 
5759         if (!rpccli_get_pwd_hash(pipe_hnd, nt_hash)) {
5760                 DEBUG(0, ("Could not retrieve password hash\n"));
5761                 goto done;
5762         }
5763 
5764         cleartextpwd = decrypt_trustdom_secret(nt_hash, &data);
5765 
5766         if (cleartextpwd == NULL) {
5767                 DEBUG(0,("retrieved NULL password\n"));
5768                 nt_status = NT_STATUS_UNSUCCESSFUL;
5769                 goto done;
5770         }
5771 
5772         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
5773                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5774                 nt_status = NT_STATUS_UNSUCCESSFUL;
5775                 goto done;
5776         }
5777 
5778 #ifdef DEBUG_PASSWORD
5779         DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
5780                    "password: [%s]\n", trusted_dom_name,
5781                    sid_string_dbg(&dom_sid), cleartextpwd));
5782 #endif
5783 
5784 done:
5785         SAFE_FREE(cleartextpwd);
5786         data_blob_free(&data);
5787 
5788         return nt_status;
5789 }
5790 
5791 static int rpc_trustdom_vampire(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
5792                                 const char **argv)
5793 {
5794         /* common variables */
5795         TALLOC_CTX* mem_ctx;
5796         struct cli_state *cli = NULL;
5797         struct rpc_pipe_client *pipe_hnd = NULL;
5798         NTSTATUS nt_status;
5799         const char *domain_name = NULL;
5800         DOM_SID *queried_dom_sid;
5801         struct policy_handle connect_hnd;
5802         union lsa_PolicyInformation *info = NULL;
5803 
5804         /* trusted domains listing variables */
5805         unsigned int enum_ctx = 0;
5806         int i;
5807         struct lsa_DomainList dom_list;
5808         fstring pdc_name;
5809 
5810         if (c->display_usage) {
5811                 d_printf("Usage:\n"
5812                          "net rpc trustdom vampire\n"
5813                          "  Vampire trust relationship from remote server\n");
5814                 return 0;
5815         }
5816 
5817         /*
5818          * Listing trusted domains (stored in secrets.tdb, if local)
5819          */
5820 
5821         mem_ctx = talloc_init("trust relationships vampire");
5822 
5823         /*
5824          * set domain and pdc name to local samba server (default)
5825          * or to remote one given in command line
5826          */
5827 
5828         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
5829                 domain_name = c->opt_workgroup;
5830                 c->opt_target_workgroup = c->opt_workgroup;
5831         } else {
5832                 fstrcpy(pdc_name, global_myname());
5833                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5834                 c->opt_target_workgroup = domain_name;
5835         };
5836 
5837         /* open \PIPE\lsarpc and open policy handle */
5838         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
5839         if (!NT_STATUS_IS_OK(nt_status)) {
5840                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5841                           nt_errstr(nt_status)));
5842                 talloc_destroy(mem_ctx);
5843                 return -1;
5844         };
5845 
5846         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5847                                              &pipe_hnd);
5848         if (!NT_STATUS_IS_OK(nt_status)) {
5849                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5850                         nt_errstr(nt_status) ));
5851                 cli_shutdown(cli);
5852                 talloc_destroy(mem_ctx);
5853                 return -1;
5854         };
5855 
5856         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
5857                                         &connect_hnd);
5858         if (NT_STATUS_IS_ERR(nt_status)) {
5859                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5860                         nt_errstr(nt_status)));
5861                 cli_shutdown(cli);
5862                 talloc_destroy(mem_ctx);
5863                 return -1;
5864         };
5865 
5866         /* query info level 5 to obtain sid of a domain being queried */
5867         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5868                                                &connect_hnd,
5869                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5870                                                &info);
5871 
5872         if (NT_STATUS_IS_ERR(nt_status)) {
5873                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5874                         nt_errstr(nt_status)));
5875                 cli_shutdown(cli);
5876                 talloc_destroy(mem_ctx);
5877                 return -1;
5878         }
5879 
5880         queried_dom_sid = info->account_domain.sid;
5881 
5882         /*
5883          * Keep calling LsaEnumTrustdom over opened pipe until
5884          * the end of enumeration is reached
5885          */
5886 
5887         d_printf("Vampire trusted domains:\n\n");
5888 
5889         do {
5890                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
5891                                                     &connect_hnd,
5892                                                     &enum_ctx,
5893                                                     &dom_list,
5894                                                     (uint32_t)-1);
5895                 if (NT_STATUS_IS_ERR(nt_status)) {
5896                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5897                                 nt_errstr(nt_status)));
5898                         cli_shutdown(cli);
5899                         talloc_destroy(mem_ctx);
5900                         return -1;
5901                 };
5902 
5903                 for (i = 0; i < dom_list.count; i++) {
5904 
5905                         print_trusted_domain(dom_list.domains[i].sid,
5906                                              dom_list.domains[i].name.string);
5907 
5908                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
5909                                                            *dom_list.domains[i].sid,
5910                                                            dom_list.domains[i].name.string);
5911                         if (!NT_STATUS_IS_OK(nt_status)) {
5912                                 cli_shutdown(cli);
5913                                 talloc_destroy(mem_ctx);
5914                                 return -1;
5915                         }
5916                 };
5917 
5918                 /*
5919                  * in case of no trusted domains say something rather
5920                  * than just display blank line
5921                  */
5922                 if (!dom_list.count) d_printf("none\n");
5923 
5924         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5925 
5926         /* close this connection before doing next one */
5927         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5928         if (NT_STATUS_IS_ERR(nt_status)) {
5929                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5930                         nt_errstr(nt_status)));
5931                 cli_shutdown(cli);
5932                 talloc_destroy(mem_ctx);
5933                 return -1;
5934         };
5935 
5936         /* close lsarpc pipe and connection to IPC$ */
5937         cli_shutdown(cli);
5938 
5939         talloc_destroy(mem_ctx);
5940         return 0;
5941 }
5942 
5943 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
5944 {
5945         /* common variables */
5946         TALLOC_CTX* mem_ctx;
5947         struct cli_state *cli = NULL, *remote_cli = NULL;
5948         struct rpc_pipe_client *pipe_hnd = NULL;
5949         NTSTATUS nt_status;
5950         const char *domain_name = NULL;
5951         DOM_SID *queried_dom_sid;
5952         int ascii_dom_name_len;
5953         struct policy_handle connect_hnd;
5954         union lsa_PolicyInformation *info = NULL;
5955 
5956         /* trusted domains listing variables */
5957         unsigned int num_domains, enum_ctx = 0;
5958         int i;
5959         struct lsa_DomainList dom_list;
5960         fstring pdc_name;
5961 
5962         /* trusting domains listing variables */
5963         struct policy_handle domain_hnd;
5964         struct samr_SamArray *trusts = NULL;
5965 
5966         if (c->display_usage) {
5967                 d_printf("Usage:\n"
5968                          "net rpc trustdom list\n"
5969                          "    List trust relationships\n");
5970                 return 0;
5971         }
5972 
5973         /*
5974          * Listing trusted domains (stored in secrets.tdb, if local)
5975          */
5976 
5977         mem_ctx = talloc_init("trust relationships listing");
5978 
5979         /*
5980          * set domain and pdc name to local samba server (default)
5981          * or to remote one given in command line
5982          */
5983 
5984         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
5985                 domain_name = c->opt_workgroup;
5986                 c->opt_target_workgroup = c->opt_workgroup;
5987         } else {
5988                 fstrcpy(pdc_name, global_myname());
5989                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5990                 c->opt_target_workgroup = domain_name;
5991         };
5992 
5993         /* open \PIPE\lsarpc and open policy handle */
5994         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
5995         if (!NT_STATUS_IS_OK(nt_status)) {
5996                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5997                           nt_errstr(nt_status)));
5998                 talloc_destroy(mem_ctx);
5999                 return -1;
6000         };
6001 
6002         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6003                                              &pipe_hnd);
6004         if (!NT_STATUS_IS_OK(nt_status)) {
6005                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6006                         nt_errstr(nt_status) ));
6007                 cli_shutdown(cli);
6008                 talloc_destroy(mem_ctx);
6009                 return -1;
6010         };
6011 
6012         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6013                                         &connect_hnd);
6014         if (NT_STATUS_IS_ERR(nt_status)) {
6015                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6016                         nt_errstr(nt_status)));
6017                 cli_shutdown(cli);
6018                 talloc_destroy(mem_ctx);
6019                 return -1;
6020         };
6021         
6022         /* query info level 5 to obtain sid of a domain being queried */
6023         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6024                                                &connect_hnd,
6025                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6026                                                &info);
6027 
6028         if (NT_STATUS_IS_ERR(nt_status)) {
6029                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6030                         nt_errstr(nt_status)));
6031                 cli_shutdown(cli);
6032                 talloc_destroy(mem_ctx);
6033                 return -1;
6034         }
6035 
6036         queried_dom_sid = info->account_domain.sid;
6037 
6038         /*
6039          * Keep calling LsaEnumTrustdom over opened pipe until
6040          * the end of enumeration is reached
6041          */
6042          
6043         d_printf("Trusted domains list:\n\n");
6044 
6045         do {
6046                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6047                                                     &connect_hnd,
6048                                                     &enum_ctx,
6049                                                     &dom_list,
6050                                                     (uint32_t)-1);
6051                 if (NT_STATUS_IS_ERR(nt_status)) {
6052                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6053                                 nt_errstr(nt_status)));
6054                         cli_shutdown(cli);
6055                         talloc_destroy(mem_ctx);
6056                         return -1;
6057                 };
6058 
6059                 for (i = 0; i < dom_list.count; i++) {
6060                         print_trusted_domain(dom_list.domains[i].sid,
6061                                              dom_list.domains[i].name.string);
6062                 };
6063 
6064                 /*
6065                  * in case of no trusted domains say something rather
6066                  * than just display blank line
6067                  */
6068                 if (!dom_list.count) d_printf("none\n");
6069 
6070         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6071 
6072         /* close this connection before doing next one */
6073         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6074         if (NT_STATUS_IS_ERR(nt_status)) {
6075                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6076                         nt_errstr(nt_status)));
6077                 cli_shutdown(cli);
6078                 talloc_destroy(mem_ctx);
6079                 return -1;
6080         };
6081         
6082         TALLOC_FREE(pipe_hnd);
6083 
6084         /*
6085          * Listing trusting domains (stored in passdb backend, if local)
6086          */
6087         
6088         d_printf("\nTrusting domains list:\n\n");
6089 
6090         /*
6091          * Open \PIPE\samr and get needed policy handles
6092          */
6093         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6094                                              &pipe_hnd);
6095         if (!NT_STATUS_IS_OK(nt_status)) {
6096                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6097                 cli_shutdown(cli);
6098                 talloc_destroy(mem_ctx);
6099                 return -1;
6100         };
6101 
6102         /* SamrConnect2 */
6103         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6104                                          pipe_hnd->desthost,
6105                                          SAMR_ACCESS_LOOKUP_DOMAIN,
6106                                          &connect_hnd);
6107         if (!NT_STATUS_IS_OK(nt_status)) {
6108                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6109                         nt_errstr(nt_status)));
6110                 cli_shutdown(cli);
6111                 talloc_destroy(mem_ctx);
6112                 return -1;
6113         };
6114 
6115         /* SamrOpenDomain - we have to open domain policy handle in order to be
6116            able to enumerate accounts*/
6117         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6118                                            &connect_hnd,
6119                                            SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6120                                            queried_dom_sid,
6121                                            &domain_hnd);
6122         if (!NT_STATUS_IS_OK(nt_status)) {
6123                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6124                         nt_errstr(nt_status)));
6125                 cli_shutdown(cli);
6126                 talloc_destroy(mem_ctx);
6127                 return -1;
6128         };
6129 
6130         /*
6131          * perform actual enumeration
6132          */
6133 
6134         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6135         do {
6136 
6137                 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6138                                                         &domain_hnd,
6139                                                         &enum_ctx,
6140                                                         ACB_DOMTRUST,
6141                                                         &trusts,
6142                                                         0xffff,
6143                                                         &num_domains);
6144                 if (NT_STATUS_IS_ERR(nt_status)) {
6145                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6146                                 nt_errstr(nt_status)));
6147                         cli_shutdown(cli);
6148                         talloc_destroy(mem_ctx);
6149                         return -1;
6150                 };
6151 
6152                 for (i = 0; i < num_domains; i++) {
6153 
6154                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6155 
6156                         /*
6157                          * get each single domain's sid (do we _really_ need this ?):
6158                          *  1) connect to domain's pdc
6159                          *  2) query the pdc for domain's sid
6160                          */
6161 
6162                         /* get rid of '$' tail */
6163                         ascii_dom_name_len = strlen(str);
6164                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6165                                 str[ascii_dom_name_len - 1] = '\0';
6166 
6167                         /* set opt_* variables to remote domain */
6168                         strupper_m(str);
6169                         c->opt_workgroup = talloc_strdup(mem_ctx, str);
6170                         c->opt_target_workgroup = c->opt_workgroup;
6171 
6172                         d_printf("%-20s", str);
6173 
6174                         /* connect to remote domain controller */
6175                         nt_status = net_make_ipc_connection(c,
6176                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6177                                         &remote_cli);
6178                         if (NT_STATUS_IS_OK(nt_status)) {
6179                                 /* query for domain's sid */
6180                                 if (run_rpc_command(
6181                                             c, remote_cli,
6182                                             &ndr_table_lsarpc.syntax_id, 0,
6183                                             rpc_query_domain_sid, argc,
6184                                             argv))
6185                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6186 
6187                                 cli_shutdown(remote_cli);
6188 
6189                         } else {
6190                                 d_fprintf(stderr, "domain controller is not "
6191                                           "responding: %s\n",
6192                                           nt_errstr(nt_status));
6193                         };
6194                 };
6195 
6196                 if (!num_domains) d_printf("none\n");
6197 
6198         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6199 
6200         /* close opened samr and domain policy handles */
6201         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6202         if (!NT_STATUS_IS_OK(nt_status)) {
6203                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6204         };
6205 
6206         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6207         if (!NT_STATUS_IS_OK(nt_status)) {
6208                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6209         };
6210 
6211         /* close samr pipe and connection to IPC$ */
6212         cli_shutdown(cli);
6213 
6214         talloc_destroy(mem_ctx);
6215         return 0;
6216 }
6217 
6218 /**
6219  * Entrypoint for 'net rpc trustdom' code.
6220  *
6221  * @param argc Standard argc.
6222  * @param argv Standard argv without initial components.
6223  *
6224  * @return Integer status (0 means success).
6225  */
6226 
6227 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6228 {
6229         struct functable func[] = {
6230                 {
6231                         "add",
6232                         rpc_trustdom_add,
6233                         NET_TRANSPORT_RPC,
6234                         "Add trusted domain's account",
6235                         "net rpc trustdom add\n"
6236                         "    Add trusted domain's account"
6237                 },
6238                 {
6239                         "del",
6240                         rpc_trustdom_del,
6241                         NET_TRANSPORT_RPC,
6242                         "Remove trusted domain's account",
6243                         "net rpc trustdom del\n"
6244                         "    Remove trusted domain's account"
6245                 },
6246                 {
6247                         "establish",
6248                         rpc_trustdom_establish,
6249                         NET_TRANSPORT_RPC,
6250                         "Establish trust relationship",
6251                         "net rpc trustdom establish\n"
6252                         "    Establish trust relationship"
6253                 },
6254                 {
6255                         "revoke",
6256                         rpc_trustdom_revoke,
6257                         NET_TRANSPORT_RPC,
6258                         "Revoke trust relationship",
6259                         "net rpc trustdom revoke\n"
6260                         "    Revoke trust relationship"
6261                 },
6262                 {
6263                         "list",
6264                         rpc_trustdom_list,
6265                         NET_TRANSPORT_RPC,
6266                         "List domain trusts",
6267                         "net rpc trustdom list\n"
6268                         "    List domain trusts"
6269                 },
6270                 {
6271                         "vampire",
6272                         rpc_trustdom_vampire,
6273                         NET_TRANSPORT_RPC,
6274                         "Vampire trusts from remote server",
6275                         "net rpc trustdom vampire\n"
6276                         "    Vampire trusts from remote server"
6277                 },
6278                 {NULL, NULL, 0, NULL, NULL}
6279         };
6280 
6281         return net_run_function(c, argc, argv, "net rpc trustdom", func);
6282 }
6283 
6284 /**
6285  * Check if a server will take rpc commands
6286  * @param flags Type of server to connect to (PDC, DMB, localhost)
6287  *              if the host is not explicitly specified
6288  * @return  bool (true means rpc supported)
6289  */
6290 bool net_rpc_check(struct net_context *c, unsigned flags)
     /* [<][>][^][v][top][bottom][index][help] */
6291 {
6292         struct cli_state *cli;
6293         bool ret = false;
6294         struct sockaddr_storage server_ss;
6295         char *server_name = NULL;
6296         NTSTATUS status;
6297 
6298         /* flags (i.e. server type) may depend on command */
6299         if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6300                 return false;
6301 
6302         if ((cli = cli_initialise()) == NULL) {
6303                 return false;
6304         }
6305 
6306         status = cli_connect(cli, server_name, &server_ss);
6307         if (!NT_STATUS_IS_OK(status))
6308                 goto done;
6309         if (!attempt_netbios_session_request(&cli, global_myname(),
6310                                              server_name, &server_ss))
6311                 goto done;
6312         status = cli_negprot(cli);
6313         if (!NT_STATUS_IS_OK(status))
6314                 goto done;
6315         if (cli->protocol < PROTOCOL_NT1)
6316                 goto done;
6317 
6318         ret = true;
6319  done:
6320         cli_shutdown(cli);
6321         return ret;
6322 }
6323 
6324 /* dump sam database via samsync rpc calls */
6325 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
     /* [<][>][^][v][top][bottom][index][help] */
6326         if (c->display_usage) {
6327                 d_printf("Usage:\n"
6328                          "net rpc samdump\n"
6329                          "    Dump remote SAM database\n");
6330                 return 0;
6331         }
6332 
6333         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6334                                NET_FLAGS_ANONYMOUS,
6335                                rpc_samdump_internals, argc, argv);
6336 }
6337 
6338 /* syncronise sam database via samsync rpc calls */
6339 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6340 {
6341         struct functable func[] = {
6342                 {
6343                         "ldif",
6344                         rpc_vampire_ldif,
6345                         NET_TRANSPORT_RPC,
6346                         "Dump remote SAM database to ldif",
6347                         "net rpc vampire ldif\n"
6348                         "    Dump remote SAM database to LDIF file or stdout"
6349                 },
6350                 {
6351                         "keytab",
6352                         rpc_vampire_keytab,
6353                         NET_TRANSPORT_RPC,
6354                         "Dump remote SAM database to Kerberos Keytab",
6355                         "net rpc vampire keytab\n"
6356                         "    Dump remote SAM database to Kerberos keytab file"
6357                 },
6358                 {
6359                         "passdb",
6360                         rpc_vampire_passdb,
6361                         NET_TRANSPORT_RPC,
6362                         "Dump remote SAM database to passdb",
6363                         "net rpc vampire passdb\n"
6364                         "    Dump remote SAM database to passdb"
6365                 },
6366 
6367                 {NULL, NULL, 0, NULL, NULL}
6368         };
6369 
6370         if (argc == 0) {
6371                 if (c->display_usage) {
6372                         d_printf("Usage:\n"
6373                                  "net rpc vampire\n"
6374                                  "    Vampire remote SAM database\n");
6375                         return 0;
6376                 }
6377 
6378                 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6379                                        NET_FLAGS_ANONYMOUS,
6380                                        rpc_vampire_internals,
6381                                        argc, argv);
6382         }
6383 
6384         return net_run_function(c, argc, argv, "net rpc vampire", func);
6385 }
6386 
6387 /**
6388  * Migrate everything from a print server.
6389  *
6390  * @param c     A net_context structure.
6391  * @param argc  Standard main() style argc.
6392  * @param argv  Standard main() style argv. Initial components are already
6393  *              stripped.
6394  *
6395  * @return A shell status integer (0 for success).
6396  *
6397  * The order is important !
6398  * To successfully add drivers the print queues have to exist !
6399  * Applying ACLs should be the last step, because you're easily locked out.
6400  *
6401  **/
6402 static int rpc_printer_migrate_all(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6403                                    const char **argv)
6404 {
6405         int ret;
6406 
6407         if (c->display_usage) {
6408                 d_printf("Usage:\n"
6409                          "net rpc printer migrate all\n"
6410                          "    Migrate everything from a print server\n");
6411                 return 0;
6412         }
6413 
6414         if (!c->opt_host) {
6415                 d_printf("no server to migrate\n");
6416                 return -1;
6417         }
6418 
6419         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6420                               rpc_printer_migrate_printers_internals, argc,
6421                               argv);
6422         if (ret)
6423                 return ret;
6424 
6425         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6426                               rpc_printer_migrate_drivers_internals, argc,
6427                               argv);
6428         if (ret)
6429                 return ret;
6430 
6431         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6432                               rpc_printer_migrate_forms_internals, argc, argv);
6433         if (ret)
6434                 return ret;
6435 
6436         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6437                               rpc_printer_migrate_settings_internals, argc,
6438                               argv);
6439         if (ret)
6440                 return ret;
6441 
6442         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6443                                rpc_printer_migrate_security_internals, argc,
6444                                argv);
6445 
6446 }
6447 
6448 /**
6449  * Migrate print drivers from a print server.
6450  *
6451  * @param c     A net_context structure.
6452  * @param argc  Standard main() style argc.
6453  * @param argv  Standard main() style argv. Initial components are already
6454  *              stripped.
6455  *
6456  * @return A shell status integer (0 for success).
6457  **/
6458 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6459                                        const char **argv)
6460 {
6461         if (c->display_usage) {
6462                 d_printf("Usage:\n"
6463                          "net rpc printer migrate drivers\n"
6464                          "     Migrate print-drivers from a print-server\n");
6465                 return 0;
6466         }
6467 
6468         if (!c->opt_host) {
6469                 d_printf("no server to migrate\n");
6470                 return -1;
6471         }
6472 
6473         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6474                                rpc_printer_migrate_drivers_internals,
6475                                argc, argv);
6476 }
6477 
6478 /**
6479  * Migrate print-forms from a print-server.
6480  *
6481  * @param c     A net_context structure.
6482  * @param argc  Standard main() style argc.
6483  * @param argv  Standard main() style argv. Initial components are already
6484  *              stripped.
6485  *
6486  * @return A shell status integer (0 for success).
6487  **/
6488 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6489                                      const char **argv)
6490 {
6491         if (c->display_usage) {
6492                 d_printf("Usage:\n"
6493                          "net rpc printer migrate forms\n"
6494                          "    Migrate print-forms from a print-server\n");
6495                 return 0;
6496         }
6497 
6498         if (!c->opt_host) {
6499                 d_printf("no server to migrate\n");
6500                 return -1;
6501         }
6502 
6503         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6504                                rpc_printer_migrate_forms_internals,
6505                                argc, argv);
6506 }
6507 
6508 /**
6509  * Migrate printers from a print-server.
6510  *
6511  * @param c     A net_context structure.
6512  * @param argc  Standard main() style argc.
6513  * @param argv  Standard main() style argv. Initial components are already
6514  *              stripped.
6515  *
6516  * @return A shell status integer (0 for success).
6517  **/
6518 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6519                                         const char **argv)
6520 {
6521         if (c->display_usage) {
6522                 d_printf("Usage:\n"
6523                          "net rpc printer migrate printers\n"
6524                          "    Migrate printers from a print-server\n");
6525                 return 0;
6526         }
6527 
6528         if (!c->opt_host) {
6529                 d_printf("no server to migrate\n");
6530                 return -1;
6531         }
6532 
6533         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6534                                rpc_printer_migrate_printers_internals,
6535                                argc, argv);
6536 }
6537 
6538 /**
6539  * Migrate printer-ACLs from a print-server
6540  *
6541  * @param c     A net_context structure.
6542  * @param argc  Standard main() style argc.
6543  * @param argv  Standard main() style argv. Initial components are already
6544  *              stripped.
6545  *
6546  * @return A shell status integer (0 for success).
6547  **/
6548 static int rpc_printer_migrate_security(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6549                                         const char **argv)
6550 {
6551         if (c->display_usage) {
6552                 d_printf("Usage:\n"
6553                          "net rpc printer migrate security\n"
6554                          "    Migrate printer-ACLs from a print-server\n");
6555                 return 0;
6556         }
6557 
6558         if (!c->opt_host) {
6559                 d_printf("no server to migrate\n");
6560                 return -1;
6561         }
6562 
6563         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6564                                rpc_printer_migrate_security_internals,
6565                                argc, argv);
6566 }
6567 
6568 /**
6569  * Migrate printer-settings from a print-server.
6570  *
6571  * @param c     A net_context structure.
6572  * @param argc  Standard main() style argc.
6573  * @param argv  Standard main() style argv. Initial components are already
6574  *              stripped.
6575  *
6576  * @return A shell status integer (0 for success).
6577  **/
6578 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6579                                         const char **argv)
6580 {
6581         if (c->display_usage) {
6582                 d_printf("Usage:\n"
6583                          "net rpc printer migrate settings\n"
6584                          "    Migrate printer-settings from a print-server\n");
6585                 return 0;
6586         }
6587 
6588         if (!c->opt_host) {
6589                 d_printf("no server to migrate\n");
6590                 return -1;
6591         }
6592 
6593         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6594                                rpc_printer_migrate_settings_internals,
6595                                argc, argv);
6596 }
6597 
6598 /**
6599  * 'net rpc printer' entrypoint.
6600  *
6601  * @param c     A net_context structure.
6602  * @param argc  Standard main() style argc.
6603  * @param argv  Standard main() style argv. Initial components are already
6604  *              stripped.
6605  **/
6606 
6607 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6608 {
6609 
6610         /* ouch: when addriver and setdriver are called from within
6611            rpc_printer_migrate_drivers_internals, the printer-queue already
6612            *has* to exist */
6613 
6614         struct functable func[] = {
6615                 {
6616                         "all",
6617                         rpc_printer_migrate_all,
6618                         NET_TRANSPORT_RPC,
6619                         "Migrate all from remote to local print server",
6620                         "net rpc printer migrate all\n"
6621                         "    Migrate all from remote to local print server"
6622                 },
6623                 {
6624                         "drivers",
6625                         rpc_printer_migrate_drivers,
6626                         NET_TRANSPORT_RPC,
6627                         "Migrate drivers to local server",
6628                         "net rpc printer migrate drivers\n"
6629                         "    Migrate drivers to local server"
6630                 },
6631                 {
6632                         "forms",
6633                         rpc_printer_migrate_forms,
6634                         NET_TRANSPORT_RPC,
6635                         "Migrate froms to local server",
6636                         "net rpc printer migrate forms\n"
6637                         "    Migrate froms to local server"
6638                 },
6639                 {
6640                         "printers",
6641                         rpc_printer_migrate_printers,
6642                         NET_TRANSPORT_RPC,
6643                         "Migrate printers to local server",
6644                         "net rpc printer migrate printers\n"
6645                         "    Migrate printers to local server"
6646                 },
6647                 {
6648                         "security",
6649                         rpc_printer_migrate_security,
6650                         NET_TRANSPORT_RPC,
6651                         "Mirgate printer ACLs to local server",
6652                         "net rpc printer migrate security\n"
6653                         "    Mirgate printer ACLs to local server"
6654                 },
6655                 {
6656                         "settings",
6657                         rpc_printer_migrate_settings,
6658                         NET_TRANSPORT_RPC,
6659                         "Migrate printer settings to local server",
6660                         "net rpc printer migrate settings\n"
6661                         "    Migrate printer settings to local server"
6662                 },
6663                 {NULL, NULL, 0, NULL, NULL}
6664         };
6665 
6666         return net_run_function(c, argc, argv, "net rpc printer migrate",func);
6667 }
6668 
6669 
6670 /**
6671  * List printers on a remote RPC server.
6672  *
6673  * @param c     A net_context structure.
6674  * @param argc  Standard main() style argc.
6675  * @param argv  Standard main() style argv. Initial components are already
6676  *              stripped.
6677  *
6678  * @return A shell status integer (0 for success).
6679  **/
6680 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6681 {
6682         if (c->display_usage) {
6683                 d_printf("Usage:\n"
6684                          "net rpc printer list\n"
6685                          "    List printers on a remote RPC server\n");
6686                 return 0;
6687         }
6688 
6689         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6690                                rpc_printer_list_internals,
6691                                argc, argv);
6692 }
6693 
6694 /**
6695  * List printer-drivers on a remote RPC server.
6696  *
6697  * @param c     A net_context structure.
6698  * @param argc  Standard main() style argc.
6699  * @param argv  Standard main() style argv. Initial components are already
6700  *              stripped.
6701  *
6702  * @return A shell status integer (0 for success).
6703  **/
6704 static int rpc_printer_driver_list(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6705                                    const char **argv)
6706 {
6707         if (c->display_usage) {
6708                 d_printf("Usage:\n"
6709                          "net rpc printer driver\n"
6710                          "    List printer-drivers on a remote RPC server\n");
6711                 return 0;
6712         }
6713 
6714         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6715                                rpc_printer_driver_list_internals,
6716                                argc, argv);
6717 }
6718 
6719 /**
6720  * Publish printer in ADS via MSRPC.
6721  *
6722  * @param c     A net_context structure.
6723  * @param argc  Standard main() style argc.
6724  * @param argv  Standard main() style argv. Initial components are already
6725  *              stripped.
6726  *
6727  * @return A shell status integer (0 for success).
6728  **/
6729 static int rpc_printer_publish_publish(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6730                                        const char **argv)
6731 {
6732         if (c->display_usage) {
6733                 d_printf("Usage:\n"
6734                          "net rpc printer publish publish\n"
6735                          "     Publish printer in ADS via MSRPC\n");
6736                 return 0;
6737         }
6738 
6739         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6740                                rpc_printer_publish_publish_internals,
6741                                argc, argv);
6742 }
6743 
6744 /**
6745  * Update printer in ADS via MSRPC.
6746  *
6747  * @param c     A net_context structure.
6748  * @param argc  Standard main() style argc.
6749  * @param argv  Standard main() style argv. Initial components are already
6750  *              stripped.
6751  *
6752  * @return A shell status integer (0 for success).
6753  **/
6754 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6755 {
6756         if (c->display_usage) {
6757                 d_printf("Usage:\n"
6758                          "net rpc printer publish update\n"
6759                          "    Update printer in ADS via MSRPC\n");
6760                 return 0;
6761         }
6762 
6763         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6764                                rpc_printer_publish_update_internals,
6765                                argc, argv);
6766 }
6767 
6768 /**
6769  * UnPublish printer in ADS via MSRPC.
6770  *
6771  * @param c     A net_context structure.
6772  * @param argc  Standard main() style argc.
6773  * @param argv  Standard main() style argv. Initial components are already
6774  *              stripped.
6775  *
6776  * @return A shell status integer (0 for success).
6777  **/
6778 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6779                                          const char **argv)
6780 {
6781         if (c->display_usage) {
6782                 d_printf("Usage:\n"
6783                          "net rpc printer publish unpublish\n"
6784                          "    UnPublish printer in ADS via MSRPC\n");
6785                 return 0;
6786         }
6787 
6788         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6789                                rpc_printer_publish_unpublish_internals,
6790                                argc, argv);
6791 }
6792 
6793 /**
6794  * List published printers via MSRPC.
6795  *
6796  * @param c     A net_context structure.
6797  * @param argc  Standard main() style argc.
6798  * @param argv  Standard main() style argv. Initial components are already
6799  *              stripped.
6800  *
6801  * @return A shell status integer (0 for success).
6802  **/
6803 static int rpc_printer_publish_list(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6804                                     const char **argv)
6805 {
6806         if (c->display_usage) {
6807                 d_printf("Usage:\n"
6808                          "net rpc printer publish list\n"
6809                          "    List published printers via MSRPC\n");
6810                 return 0;
6811         }
6812 
6813         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6814                                rpc_printer_publish_list_internals,
6815                                argc, argv);
6816 }
6817 
6818 
6819 /**
6820  * Publish printer in ADS.
6821  *
6822  * @param c     A net_context structure.
6823  * @param argc  Standard main() style argc.
6824  * @param argv  Standard main() style argv. Initial components are already
6825  *              stripped.
6826  *
6827  * @return A shell status integer (0 for success).
6828  **/
6829 static int rpc_printer_publish(struct net_context *c, int argc,
     /* [<][>][^][v][top][bottom][index][help] */
6830                                const char **argv)
6831 {
6832 
6833         struct functable func[] = {
6834                 {
6835                         "publish",
6836                         rpc_printer_publish_publish,
6837                         NET_TRANSPORT_RPC,
6838                         "Publish printer in AD",
6839                         "net rpc printer publish publish\n"
6840                         "    Publish printer in AD"
6841                 },
6842                 {
6843                         "update",
6844                         rpc_printer_publish_update,
6845                         NET_TRANSPORT_RPC,
6846                         "Update printer in AD",
6847                         "net rpc printer publish update\n"
6848                         "    Update printer in AD"
6849                 },
6850                 {
6851                         "unpublish",
6852                         rpc_printer_publish_unpublish,
6853                         NET_TRANSPORT_RPC,
6854                         "Unpublish printer",
6855                         "net rpc printer publish unpublish\n"
6856                         "    Unpublish printer"
6857                 },
6858                 {
6859                         "list",
6860                         rpc_printer_publish_list,
6861                         NET_TRANSPORT_RPC,
6862                         "List published printers",
6863                         "net rpc printer publish list\n"
6864                         "    List published printers"
6865                 },
6866                 {NULL, NULL, 0, NULL, NULL}
6867         };
6868 
6869         if (argc == 0) {
6870                 if (c->display_usage) {
6871                         d_printf("Usage:\n");
6872                         d_printf("net rpc printer publish\n"
6873                                  "    List published printers\n"
6874                                  "    Alias of net rpc printer publish list\n");
6875                         net_display_usage_from_functable(func);
6876                         return 0;
6877                 }
6878                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6879                                rpc_printer_publish_list_internals,
6880                                argc, argv);
6881         }
6882 
6883         return net_run_function(c, argc, argv, "net rpc printer publish",func);
6884 
6885 }
6886 
6887 
6888 /**
6889  * Display rpc printer help page.
6890  *
6891  * @param c     A net_context structure.
6892  * @param argc  Standard main() style argc.
6893  * @param argv  Standard main() style argv. Initial components are already
6894  *              stripped.
6895  **/
6896 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6897 {
6898         d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"
6899                  "\tlists all printers on print-server\n\n");
6900         d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
6901                  "\tlists all printer-drivers on print-server\n\n");
6902         d_printf("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
6903                  "\tpublishes printer settings in Active Directory\n"
6904                  "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n");
6905         d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
6906                  "\n\tmigrates printers from remote to local server\n\n");
6907         d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
6908                  "\n\tmigrates printer-settings from remote to local server\n\n");
6909         d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
6910                  "\n\tmigrates printer-drivers from remote to local server\n\n");
6911         d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
6912                  "\n\tmigrates printer-forms from remote to local server\n\n");
6913         d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
6914                  "\n\tmigrates printer-ACLs from remote to local server\n\n");
6915         d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
6916                  "\n\tmigrates drivers, forms, queues, settings and acls from\n"
6917                  "\tremote to local print-server\n\n");
6918         net_common_methods_usage(c, argc, argv);
6919         net_common_flags_usage(c, argc, argv);
6920         d_printf(
6921          "\t-v or --verbose\t\t\tgive verbose output\n"
6922          "\t      --destination\t\tmigration target server (default: localhost)\n");
6923 
6924         return -1;
6925 }
6926 
6927 /**
6928  * 'net rpc printer' entrypoint.
6929  *
6930  * @param c     A net_context structure.
6931  * @param argc  Standard main() style argc.
6932  * @param argv  Standard main() style argv. Initial components are already
6933  *              stripped.
6934  **/
6935 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6936 {
6937         struct functable func[] = {
6938                 {
6939                         "list",
6940                         rpc_printer_list,
6941                         NET_TRANSPORT_RPC,
6942                         "List all printers on print server",
6943                         "net rpc printer list\n"
6944                         "    List all printers on print server"
6945                 },
6946                 {
6947                         "migrate",
6948                         rpc_printer_migrate,
6949                         NET_TRANSPORT_RPC,
6950                         "Migrate printer to local server",
6951                         "net rpc printer migrate\n"
6952                         "    Migrate printer to local server"
6953                 },
6954                 {
6955                         "driver",
6956                         rpc_printer_driver_list,
6957                         NET_TRANSPORT_RPC,
6958                         "List printer drivers",
6959                         "net rpc printer driver\n"
6960                         "    List printer drivers"
6961                 },
6962                 {
6963                         "publish",
6964                         rpc_printer_publish,
6965                         NET_TRANSPORT_RPC,
6966                         "Publish printer in AD",
6967                         "net rpc printer publish\n"
6968                         "    Publish printer in AD"
6969                 },
6970                 {NULL, NULL, 0, NULL, NULL}
6971         };
6972 
6973         if (argc == 0) {
6974                 if (c->display_usage) {
6975                         d_printf("Usage:\n");
6976                         d_printf("net rpc printer\n"
6977                                  "    List printers\n");
6978                         net_display_usage_from_functable(func);
6979                         return 0;
6980                 }
6981                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6982                                rpc_printer_list_internals,
6983                                argc, argv);
6984         }
6985 
6986         return net_run_function(c, argc, argv, "net rpc printer", func);
6987 }
6988 
6989 /**
6990  * 'net rpc' entrypoint.
6991  *
6992  * @param c     A net_context structure.
6993  * @param argc  Standard main() style argc.
6994  * @param argv  Standard main() style argv. Initial components are already
6995  *              stripped.
6996  **/
6997 
6998 int net_rpc(struct net_context *c, int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
6999 {
7000         NET_API_STATUS status;
7001 
7002         struct functable func[] = {
7003                 {
7004                         "audit",
7005                         net_rpc_audit,
7006                         NET_TRANSPORT_RPC,
7007                         "Modify global audit settings",
7008                         "net rpc audit\n"
7009                         "    Modify global audit settings"
7010                 },
7011                 {
7012                         "info",
7013                         net_rpc_info,
7014                         NET_TRANSPORT_RPC,
7015                         "Show basic info about a domain",
7016                         "net rpc info\n"
7017                         "    Show basic info about a domain"
7018                 },
7019                 {
7020                         "join",
7021                         net_rpc_join,
7022                         NET_TRANSPORT_RPC,
7023                         "Join a domain",
7024                         "net rpc join\n"
7025                         "    Join a domain"
7026                 },
7027                 {
7028                         "oldjoin",
7029                         net_rpc_oldjoin,
7030                         NET_TRANSPORT_RPC,
7031                         "Join a domain created in server manager",
7032                         "net rpc oldjoin\n"
7033                         "    Join a domain created in server manager"
7034                 },
7035                 {
7036                         "testjoin",
7037                         net_rpc_testjoin,
7038                         NET_TRANSPORT_RPC,
7039                         "Test that a join is valid",
7040                         "net rpc testjoin\n"
7041                         "    Test that a join is valid"
7042                 },
7043                 {
7044                         "user",
7045                         net_rpc_user,
7046                         NET_TRANSPORT_RPC,
7047                         "List/modify users",
7048                         "net rpc user\n"
7049                         "    List/modify users"
7050                 },
7051                 {
7052                         "password",
7053                         rpc_user_password,
7054                         NET_TRANSPORT_RPC,
7055                         "Change a user password",
7056                         "net rpc password\n"
7057                         "    Change a user password\n"
7058                         "    Alias for net rpc user password"
7059                 },
7060                 {
7061                         "group",
7062                         net_rpc_group,
7063                         NET_TRANSPORT_RPC,
7064                         "List/modify groups",
7065                         "net rpc group\n"
7066                         "    List/modify groups"
7067                 },
7068                 {
7069                         "share",
7070                         net_rpc_share,
7071                         NET_TRANSPORT_RPC,
7072                         "List/modify shares",
7073                         "net rpc share\n"
7074                         "    List/modify shares"
7075                 },
7076                 {
7077                         "file",
7078                         net_rpc_file,
7079                         NET_TRANSPORT_RPC,
7080                         "List open files",
7081                         "net rpc file\n"
7082                         "    List open files"
7083                 },
7084                 {
7085                         "printer",
7086                         net_rpc_printer,
7087                         NET_TRANSPORT_RPC,
7088                         "List/modify printers",
7089                         "net rpc printer\n"
7090                         "    List/modify printers"
7091                 },
7092                 {
7093                         "changetrustpw",
7094                         net_rpc_changetrustpw,
7095                         NET_TRANSPORT_RPC,
7096                         "Change trust account password",
7097                         "net rpc changetrustpw\n"
7098                         "    Change trust account password"
7099                 },
7100                 {
7101                         "trustdom",
7102                         rpc_trustdom,
7103                         NET_TRANSPORT_RPC,
7104                         "Modify domain trusts",
7105                         "net rpc trustdom\n"
7106                         "    Modify domain trusts"
7107                 },
7108                 {
7109                         "abortshutdown",
7110                         rpc_shutdown_abort,
7111                         NET_TRANSPORT_RPC,
7112                         "Abort a remote shutdown",
7113                         "net rpc abortshutdown\n"
7114                         "    Abort a remote shutdown"
7115                 },
7116                 {
7117                         "shutdown",
7118                         rpc_shutdown,
7119                         NET_TRANSPORT_RPC,
7120                         "Shutdown a remote server",
7121                         "net rpc shutdown\n"
7122                         "    Shutdown a remote server"
7123                 },
7124                 {
7125                         "samdump",
7126                         rpc_samdump,
7127                         NET_TRANSPORT_RPC,
7128                         "Dump SAM data of remote NT PDC",
7129                         "net rpc samdump\n"
7130                         "    Dump SAM data of remote NT PDC"
7131                 },
7132                 {
7133                         "vampire",
7134                         rpc_vampire,
7135                         NET_TRANSPORT_RPC,
7136                         "Sync a remote NT PDC's data into local passdb",
7137                         "net rpc vampire\n"
7138                         "    Sync a remote NT PDC's data into local passdb"
7139                 },
7140                 {
7141                         "getsid",
7142                         net_rpc_getsid,
7143                         NET_TRANSPORT_RPC,
7144                         "Fetch the domain sid into local secrets.tdb",
7145                         "net rpc getsid\n"
7146                         "    Fetch the domain sid into local secrets.tdb"
7147                 },
7148                 {
7149                         "rights",
7150                         net_rpc_rights,
7151                         NET_TRANSPORT_RPC,
7152                         "Manage privileges assigned to SID",
7153                         "net rpc rights\n"
7154                         "    Manage privileges assigned to SID"
7155                 },
7156                 {
7157                         "service",
7158                         net_rpc_service,
7159                         NET_TRANSPORT_RPC,
7160                         "Start/stop/query remote services",
7161                         "net rpc service\n"
7162                         "    Start/stop/query remote services"
7163                 },
7164                 {
7165                         "registry",
7166                         net_rpc_registry,
7167                         NET_TRANSPORT_RPC,
7168                         "Manage registry hives",
7169                         "net rpc registry\n"
7170                         "    Manage registry hives"
7171                 },
7172                 {
7173                         "shell",
7174                         net_rpc_shell,
7175                         NET_TRANSPORT_RPC,
7176                         "Open interactive shell on remote server",
7177                         "net rpc shell\n"
7178                         "    Open interactive shell on remote server"
7179                 },
7180                 {NULL, NULL, 0, NULL, NULL}
7181         };
7182 
7183         status = libnetapi_init(&c->netapi_ctx);
7184         if (status != 0) {
7185                 return -1;
7186         }
7187         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7188         libnetapi_set_password(c->netapi_ctx, c->opt_password);
7189         if (c->opt_kerberos) {
7190                 libnetapi_set_use_kerberos(c->netapi_ctx);
7191         }
7192 
7193         return net_run_function(c, argc, argv, "net rpc", func);
7194 }

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