utils/net_rpc.c

説明を見る。
00001 /* 
00002    Samba Unix/Linux SMB client library 
00003    Distributed SMB/CIFS Server Management Utility 
00004    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
00005    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
00006    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
00007    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
00022  
00023 #include "includes.h"
00024 #include "utils/net.h"
00025 
00026 static int net_mode_share;
00027 
00028 /**
00029  * @file net_rpc.c
00030  *
00031  * @brief RPC based subcommands for the 'net' utility.
00032  *
00033  * This file should contain much of the functionality that used to
00034  * be found in rpcclient, execpt that the commands should change 
00035  * less often, and the fucntionality should be sane (the user is not 
00036  * expected to know a rid/sid before they conduct an operation etc.)
00037  *
00038  * @todo Perhaps eventually these should be split out into a number
00039  * of files, as this could get quite big.
00040  **/
00041 
00042 
00043 /**
00044  * Many of the RPC functions need the domain sid.  This function gets
00045  *  it at the start of every run 
00046  *
00047  * @param cli A cli_state already connected to the remote machine
00048  *
00049  * @return The Domain SID of the remote machine.
00050  **/
00051 
00052 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
00053                                    DOM_SID **domain_sid, char **domain_name)
00054 {
00055         struct rpc_pipe_client *lsa_pipe;
00056         POLICY_HND pol;
00057         NTSTATUS result = NT_STATUS_OK;
00058         uint32 info_class = 5;
00059         
00060         lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
00061         if (!lsa_pipe) {
00062                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
00063                 return result;
00064         }
00065         
00066         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, 
00067                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
00068                                      &pol);
00069         if (!NT_STATUS_IS_OK(result)) {
00070                 d_fprintf(stderr, "open_policy failed: %s\n",
00071                           nt_errstr(result));
00072                 return result;
00073         }
00074 
00075         result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol,
00076                                               info_class, domain_name,
00077                                               domain_sid);
00078         if (!NT_STATUS_IS_OK(result)) {
00079                 d_fprintf(stderr, "lsaquery failed: %s\n",
00080                           nt_errstr(result));
00081                 return result;
00082         }
00083 
00084         rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
00085         cli_rpc_pipe_close(lsa_pipe);
00086 
00087         return NT_STATUS_OK;
00088 }
00089 
00090 /**
00091  * Run a single RPC command, from start to finish.
00092  *
00093  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
00094  * @param conn_flag a NET_FLAG_ combination.  Passed to 
00095  *                   net_make_ipc_connection.
00096  * @param argc  Standard main() style argc
00097  * @param argc  Standard main() style argv.  Initial components are already
00098  *              stripped
00099  * @return A shell status integer (0 for success)
00100  */
00101 
00102 int run_rpc_command(struct cli_state *cli_arg,
00103                         const int pipe_idx,
00104                         int conn_flags,
00105                         rpc_command_fn fn,
00106                         int argc,
00107                         const char **argv) 
00108 {
00109         struct cli_state *cli = NULL;
00110         struct rpc_pipe_client *pipe_hnd = NULL;
00111         TALLOC_CTX *mem_ctx;
00112         NTSTATUS nt_status;
00113         DOM_SID *domain_sid;
00114         char *domain_name;
00115 
00116         /* make use of cli_state handed over as an argument, if possible */
00117         if (!cli_arg) {
00118                 cli = net_make_ipc_connection(conn_flags);
00119         } else {
00120                 cli = cli_arg;
00121         }
00122 
00123         if (!cli) {
00124                 return -1;
00125         }
00126 
00127         /* Create mem_ctx */
00128         
00129         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
00130                 DEBUG(0, ("talloc_init() failed\n"));
00131                 cli_shutdown(cli);
00132                 return -1;
00133         }
00134         
00135         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
00136                                               &domain_name);
00137         if (!NT_STATUS_IS_OK(nt_status)) {
00138                 cli_shutdown(cli);
00139                 return -1;
00140         }
00141 
00142         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
00143                 if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
00144                         /* Always try and create an schannel netlogon pipe. */
00145                         pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx,
00146                                                         PIPE_AUTH_LEVEL_PRIVACY,
00147                                                         domain_name,
00148                                                         &nt_status);
00149                         if (!pipe_hnd) {
00150                                 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
00151                                         nt_errstr(nt_status) ));
00152                                 cli_shutdown(cli);
00153                                 return -1;
00154                         }
00155                 } else {
00156                         pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status);
00157                         if (!pipe_hnd) {
00158                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
00159                                         cli_get_pipe_name(pipe_idx),
00160                                         nt_errstr(nt_status) ));
00161                                 cli_shutdown(cli);
00162                                 return -1;
00163                         }
00164                 }
00165         }
00166         
00167         nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
00168         
00169         if (!NT_STATUS_IS_OK(nt_status)) {
00170                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
00171         } else {
00172                 DEBUG(5, ("rpc command function succedded\n"));
00173         }
00174                 
00175         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
00176                 if (pipe_hnd) {
00177                         cli_rpc_pipe_close(pipe_hnd);
00178                 }
00179         }
00180 
00181         /* close the connection only if it was opened here */
00182         if (!cli_arg) {
00183                 cli_shutdown(cli);
00184         }
00185         
00186         talloc_destroy(mem_ctx);
00187         return (!NT_STATUS_IS_OK(nt_status));
00188 }
00189 
00190 /** 
00191  * Force a change of the trust acccount password.
00192  *
00193  * All parameters are provided by the run_rpc_command function, except for
00194  * argc, argv which are passes through. 
00195  *
00196  * @param domain_sid The domain sid aquired from the remote server
00197  * @param cli A cli_state connected to the server.
00198  * @param mem_ctx Talloc context, destoyed on compleation of the function.
00199  * @param argc  Standard main() style argc
00200  * @param argc  Standard main() style argv.  Initial components are already
00201  *              stripped
00202  *
00203  * @return Normal NTSTATUS return.
00204  **/
00205 
00206 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid,
00207                                         const char *domain_name, 
00208                                         struct cli_state *cli,
00209                                         struct rpc_pipe_client *pipe_hnd,
00210                                         TALLOC_CTX *mem_ctx, 
00211                                         int argc,
00212                                         const char **argv)
00213 {
00214         
00215         return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup);
00216 }
00217 
00218 /** 
00219  * Force a change of the trust acccount password.
00220  *
00221  * @param argc  Standard main() style argc
00222  * @param argc  Standard main() style argv.  Initial components are already
00223  *              stripped
00224  *
00225  * @return A shell status integer (0 for success)
00226  **/
00227 
00228 int net_rpc_changetrustpw(int argc, const char **argv) 
00229 {
00230         net_use_machine_account();
00231 
00232         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
00233                                rpc_changetrustpw_internals,
00234                                argc, argv);
00235 }
00236 
00237 /** 
00238  * Join a domain, the old way.
00239  *
00240  * This uses 'machinename' as the inital password, and changes it. 
00241  *
00242  * The password should be created with 'server manager' or equiv first.
00243  *
00244  * All parameters are provided by the run_rpc_command function, except for
00245  * argc, argv which are passes through. 
00246  *
00247  * @param domain_sid The domain sid aquired from the remote server
00248  * @param cli A cli_state connected to the server.
00249  * @param mem_ctx Talloc context, destoyed on compleation of the function.
00250  * @param argc  Standard main() style argc
00251  * @param argc  Standard main() style argv.  Initial components are already
00252  *              stripped
00253  *
00254  * @return Normal NTSTATUS return.
00255  **/
00256 
00257 static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid,
00258                                         const char *domain_name, 
00259                                         struct cli_state *cli, 
00260                                         struct rpc_pipe_client *pipe_hnd,
00261                                         TALLOC_CTX *mem_ctx, 
00262                                         int argc,
00263                                         const char **argv)
00264 {
00265         
00266         fstring trust_passwd;
00267         unsigned char orig_trust_passwd_hash[16];
00268         NTSTATUS result;
00269         uint32 sec_channel_type;
00270 
00271         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
00272         if (!pipe_hnd) {
00273                 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
00274                         "error was %s\n",
00275                         cli->desthost,
00276                         nt_errstr(result) ));
00277                 return result;
00278         }
00279 
00280         /* 
00281            check what type of join - if the user want's to join as
00282            a BDC, the server must agree that we are a BDC.
00283         */
00284         if (argc >= 0) {
00285                 sec_channel_type = get_sec_channel_type(argv[0]);
00286         } else {
00287                 sec_channel_type = get_sec_channel_type(NULL);
00288         }
00289         
00290         fstrcpy(trust_passwd, global_myname());
00291         strlower_m(trust_passwd);
00292 
00293         /*
00294          * Machine names can be 15 characters, but the max length on
00295          * a password is 14.  --jerry
00296          */
00297 
00298         trust_passwd[14] = '\0';
00299 
00300         E_md4hash(trust_passwd, orig_trust_passwd_hash);
00301 
00302         result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup,
00303                                               orig_trust_passwd_hash,
00304                                               sec_channel_type);
00305 
00306         if (NT_STATUS_IS_OK(result))
00307                 printf("Joined domain %s.\n",opt_target_workgroup);
00308 
00309 
00310         if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
00311                 DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
00312                 result = NT_STATUS_UNSUCCESSFUL;
00313         }
00314 
00315         return result;
00316 }
00317 
00318 /** 
00319  * Join a domain, the old way.
00320  *
00321  * @param argc  Standard main() style argc
00322  * @param argc  Standard main() style argv.  Initial components are already
00323  *              stripped
00324  *
00325  * @return A shell status integer (0 for success)
00326  **/
00327 
00328 static int net_rpc_perform_oldjoin(int argc, const char **argv)
00329 {
00330         return run_rpc_command(NULL, PI_NETLOGON, 
00331                                NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
00332                                rpc_oldjoin_internals,
00333                                argc, argv);
00334 }
00335 
00336 /** 
00337  * Join a domain, the old way.  This function exists to allow
00338  * the message to be displayed when oldjoin was explicitly 
00339  * requested, but not when it was implied by "net rpc join"
00340  *
00341  * @param argc  Standard main() style argc
00342  * @param argc  Standard main() style argv.  Initial components are already
00343  *              stripped
00344  *
00345  * @return A shell status integer (0 for success)
00346  **/
00347 
00348 static int net_rpc_oldjoin(int argc, const char **argv) 
00349 {
00350         int rc = net_rpc_perform_oldjoin(argc, argv);
00351 
00352         if (rc) {
00353                 d_fprintf(stderr, "Failed to join domain\n");
00354         }
00355 
00356         return rc;
00357 }
00358 
00359 /** 
00360  * Basic usage function for 'net rpc join'
00361  * @param argc  Standard main() style argc
00362  * @param argc  Standard main() style argv.  Initial components are already
00363  *              stripped
00364  **/
00365 
00366 static int rpc_join_usage(int argc, const char **argv) 
00367 {       
00368         d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
00369                  "\t to join a domain with admin username & password\n"\
00370                  "\t\t password will be prompted if needed and none is specified\n"\
00371                  "\t <type> can be (default MEMBER)\n"\
00372                  "\t\t BDC - Join as a BDC\n"\
00373                  "\t\t PDC - Join as a PDC\n"\
00374                  "\t\t MEMBER - Join as a MEMBER server\n");
00375 
00376         net_common_flags_usage(argc, argv);
00377         return -1;
00378 }
00379 
00380 /** 
00381  * 'net rpc join' entrypoint.
00382  * @param argc  Standard main() style argc
00383  * @param argc  Standard main() style argv.  Initial components are already
00384  *              stripped
00385  *
00386  * Main 'net_rpc_join()' (where the admin username/password is used) is
00387  * in net_rpc_join.c
00388  * Try to just change the password, but if that doesn't work, use/prompt
00389  * for a username/password.
00390  **/
00391 
00392 int net_rpc_join(int argc, const char **argv) 
00393 {
00394         if (lp_server_role() == ROLE_STANDALONE) {
00395                 d_printf("cannot join as standalone machine\n");
00396                 return -1;
00397         }
00398 
00399         if (strlen(global_myname()) > 15) {
00400                 d_printf("Our netbios name can be at most 15 chars long, "
00401                          "\"%s\" is %u chars long\n",
00402                          global_myname(), (unsigned int)strlen(global_myname()));
00403                 return -1;
00404         }
00405 
00406         if ((net_rpc_perform_oldjoin(argc, argv) == 0))
00407                 return 0;
00408         
00409         return net_rpc_join_newstyle(argc, argv);
00410 }
00411 
00412 /** 
00413  * display info about a rpc domain
00414  *
00415  * All parameters are provided by the run_rpc_command function, except for
00416  * argc, argv which are passed through. 
00417  *
00418  * @param domain_sid The domain sid acquired from the remote server
00419  * @param cli A cli_state connected to the server.
00420  * @param mem_ctx Talloc context, destoyed on completion of the function.
00421  * @param argc  Standard main() style argc
00422  * @param argv  Standard main() style argv.  Initial components are already
00423  *              stripped
00424  *
00425  * @return Normal NTSTATUS return.
00426  **/
00427 
00428 NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
00429                         const char *domain_name, 
00430                         struct cli_state *cli,
00431                         struct rpc_pipe_client *pipe_hnd,
00432                         TALLOC_CTX *mem_ctx,
00433                         int argc,
00434                         const char **argv)
00435 {
00436         POLICY_HND connect_pol, domain_pol;
00437         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00438         SAM_UNK_CTR ctr;
00439         fstring sid_str;
00440 
00441         sid_to_string(sid_str, domain_sid);
00442 
00443         /* Get sam policy handle */     
00444         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
00445                                   &connect_pol);
00446         if (!NT_STATUS_IS_OK(result)) {
00447                 d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
00448                 goto done;
00449         }
00450         
00451         /* Get domain policy handle */
00452         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
00453                                       MAXIMUM_ALLOWED_ACCESS,
00454                                       domain_sid, &domain_pol);
00455         if (!NT_STATUS_IS_OK(result)) {
00456                 d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
00457                 goto done;
00458         }
00459 
00460         ZERO_STRUCT(ctr);
00461         result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
00462                                          2, &ctr);
00463         if (NT_STATUS_IS_OK(result)) {
00464                 TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
00465                 d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain));
00466                 d_printf("Domain SID: %s\n", sid_str);
00467                 d_printf("Sequence number: %llu\n", (unsigned long long)ctr.info.inf2.seq_num);
00468                 d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
00469                 d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
00470                 d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps);
00471                 talloc_destroy(ctx);
00472         }
00473 
00474  done:
00475         return result;
00476 }
00477 
00478 /** 
00479  * 'net rpc info' entrypoint.
00480  * @param argc  Standard main() style argc
00481  * @param argc  Standard main() style argv.  Initial components are already
00482  *              stripped
00483  **/
00484 
00485 int net_rpc_info(int argc, const char **argv) 
00486 {
00487         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_PDC, 
00488                                rpc_info_internals,
00489                                argc, argv);
00490 }
00491 
00492 /** 
00493  * Fetch domain SID into the local secrets.tdb
00494  *
00495  * All parameters are provided by the run_rpc_command function, except for
00496  * argc, argv which are passes through. 
00497  *
00498  * @param domain_sid The domain sid acquired from the remote server
00499  * @param cli A cli_state connected to the server.
00500  * @param mem_ctx Talloc context, destoyed on completion of the function.
00501  * @param argc  Standard main() style argc
00502  * @param argv  Standard main() style argv.  Initial components are already
00503  *              stripped
00504  *
00505  * @return Normal NTSTATUS return.
00506  **/
00507 
00508 static NTSTATUS rpc_getsid_internals(const DOM_SID *domain_sid,
00509                         const char *domain_name, 
00510                         struct cli_state *cli,
00511                         struct rpc_pipe_client *pipe_hnd,
00512                         TALLOC_CTX *mem_ctx,
00513                         int argc,
00514                         const char **argv)
00515 {
00516         fstring sid_str;
00517 
00518         sid_to_string(sid_str, domain_sid);
00519         d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
00520                  sid_str, domain_name);
00521 
00522         if (!secrets_store_domain_sid(domain_name, domain_sid)) {
00523                 DEBUG(0,("Can't store domain SID\n"));
00524                 return NT_STATUS_UNSUCCESSFUL;
00525         }
00526 
00527         return NT_STATUS_OK;
00528 }
00529 
00530 /** 
00531  * 'net rpc getsid' entrypoint.
00532  * @param argc  Standard main() style argc
00533  * @param argc  Standard main() style argv.  Initial components are already
00534  *              stripped
00535  **/
00536 
00537 int net_rpc_getsid(int argc, const char **argv) 
00538 {
00539         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
00540                                rpc_getsid_internals,
00541                                argc, argv);
00542 }
00543 
00544 /****************************************************************************/
00545 
00546 /**
00547  * Basic usage function for 'net rpc user'
00548  * @param argc  Standard main() style argc.
00549  * @param argv  Standard main() style argv.  Initial components are already
00550  *              stripped.
00551  **/
00552 
00553 static int rpc_user_usage(int argc, const char **argv)
00554 {
00555         return net_help_user(argc, argv);
00556 }
00557 
00558 /** 
00559  * Add a new user to a remote RPC server
00560  *
00561  * All parameters are provided by the run_rpc_command function, except for
00562  * argc, argv which are passes through. 
00563  *
00564  * @param domain_sid The domain sid acquired from the remote server
00565  * @param cli A cli_state connected to the server.
00566  * @param mem_ctx Talloc context, destoyed on completion of the function.
00567  * @param argc  Standard main() style argc
00568  * @param argv  Standard main() style argv.  Initial components are already
00569  *              stripped
00570  *
00571  * @return Normal NTSTATUS return.
00572  **/
00573 
00574 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
00575                                 const char *domain_name, 
00576                                 struct cli_state *cli,
00577                                 struct rpc_pipe_client *pipe_hnd,
00578                                 TALLOC_CTX *mem_ctx, 
00579                                 int argc, const char **argv)
00580 {
00581         
00582         POLICY_HND connect_pol, domain_pol, user_pol;
00583         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00584         const char *acct_name;
00585         uint32 acb_info;
00586         uint32 acct_flags=0;
00587         uint32 user_rid;
00588 
00589         if (argc < 1) {
00590                 d_printf("User must be specified\n");
00591                 rpc_user_usage(argc, argv);
00592                 return NT_STATUS_OK;
00593         }
00594 
00595         acct_name = argv[0];
00596 
00597         /* Get sam policy handle */
00598         
00599         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
00600                                   &connect_pol);
00601         if (!NT_STATUS_IS_OK(result)) {
00602                 goto done;
00603         }
00604         
00605         /* Get domain policy handle */
00606         
00607         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
00608                                       MAXIMUM_ALLOWED_ACCESS,
00609                                       domain_sid, &domain_pol);
00610         if (!NT_STATUS_IS_OK(result)) {
00611                 goto done;
00612         }
00613 
00614         /* Create domain user */
00615 
00616         acb_info = ACB_NORMAL;
00617         acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
00618                 SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
00619                 SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
00620                 SAMR_USER_SETATTR;
00621         DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
00622 
00623         result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
00624                                           acct_name, acb_info, acct_flags,
00625                                           &user_pol, &user_rid);
00626         if (!NT_STATUS_IS_OK(result)) {
00627                 goto done;
00628         }
00629 
00630         if (argc == 2) {
00631 
00632                 uint32 *user_rids, num_rids, *name_types;
00633                 uint32 flags = 0x000003e8; /* Unknown */
00634                 SAM_USERINFO_CTR ctr;
00635                 SAM_USER_INFO_24 p24;
00636                 uchar pwbuf[516];
00637 
00638                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
00639                                                   flags, 1, &acct_name,
00640                                                   &num_rids, &user_rids,
00641                                                   &name_types);
00642 
00643                 if (!NT_STATUS_IS_OK(result)) {
00644                         goto done;
00645                 }
00646 
00647                 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
00648                                                MAXIMUM_ALLOWED_ACCESS,
00649                                                user_rids[0], &user_pol);
00650 
00651                 if (!NT_STATUS_IS_OK(result)) {
00652                         goto done;
00653                 }
00654 
00655                 /* Set password on account */
00656 
00657                 ZERO_STRUCT(ctr);
00658                 ZERO_STRUCT(p24);
00659 
00660                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
00661 
00662                 init_sam_user_info24(&p24, (char *)pwbuf,24);
00663 
00664                 ctr.switch_value = 24;
00665                 ctr.info.id24 = &p24;
00666 
00667                 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 
00668                                                &cli->user_session_key, &ctr);
00669 
00670                 if (!NT_STATUS_IS_OK(result)) {
00671                         d_fprintf(stderr, "Failed to set password for user %s - %s\n", 
00672                                  acct_name, nt_errstr(result));
00673 
00674                         result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
00675 
00676                         if (!NT_STATUS_IS_OK(result)) {
00677                                 d_fprintf(stderr, "Failed to delete user %s - %s\n", 
00678                                          acct_name, nt_errstr(result));
00679                                  return result;
00680                         }
00681                 }
00682 
00683         }
00684  done:
00685         if (!NT_STATUS_IS_OK(result)) {
00686                 d_fprintf(stderr, "Failed to add user %s - %s\n", acct_name, 
00687                          nt_errstr(result));
00688         } else {
00689                 d_printf("Added user %s\n", acct_name);
00690         }
00691         return result;
00692 }
00693 
00694 /** 
00695  * Add a new user to a remote RPC server
00696  *
00697  * @param argc  Standard main() style argc
00698  * @param argv  Standard main() style argv.  Initial components are already
00699  *              stripped
00700  *
00701  * @return A shell status integer (0 for success)
00702  **/
00703 
00704 static int rpc_user_add(int argc, const char **argv) 
00705 {
00706         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_add_internals,
00707                                argc, argv);
00708 }
00709 
00710 /** 
00711  * Delete a user from a remote RPC server
00712  *
00713  * All parameters are provided by the run_rpc_command function, except for
00714  * argc, argv which are passes through. 
00715  *
00716  * @param domain_sid The domain sid acquired from the remote server
00717  * @param cli A cli_state connected to the server.
00718  * @param mem_ctx Talloc context, destoyed on completion of the function.
00719  * @param argc  Standard main() style argc
00720  * @param argv  Standard main() style argv.  Initial components are already
00721  *              stripped
00722  *
00723  * @return Normal NTSTATUS return.
00724  **/
00725 
00726 static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, 
00727                                         const char *domain_name, 
00728                                         struct cli_state *cli, 
00729                                         struct rpc_pipe_client *pipe_hnd,
00730                                         TALLOC_CTX *mem_ctx, 
00731                                         int argc,
00732                                         const char **argv)
00733 {
00734         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00735         POLICY_HND connect_pol, domain_pol, user_pol;
00736 
00737         if (argc < 1) {
00738                 d_printf("User must be specified\n");
00739                 rpc_user_usage(argc, argv);
00740                 return NT_STATUS_OK;
00741         }
00742         /* Get sam policy and domain handles */
00743 
00744         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
00745                                   &connect_pol);
00746 
00747         if (!NT_STATUS_IS_OK(result)) {
00748                 goto done;
00749         }
00750 
00751         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
00752                                       MAXIMUM_ALLOWED_ACCESS,
00753                                       domain_sid, &domain_pol);
00754 
00755         if (!NT_STATUS_IS_OK(result)) {
00756                 goto done;
00757         }
00758 
00759         /* Get handle on user */
00760 
00761         {
00762                 uint32 *user_rids, num_rids, *name_types;
00763                 uint32 flags = 0x000003e8; /* Unknown */
00764 
00765                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
00766                                                flags, 1, &argv[0],
00767                                                &num_rids, &user_rids,
00768                                                &name_types);
00769 
00770                 if (!NT_STATUS_IS_OK(result)) {
00771                         goto done;
00772                 }
00773 
00774                 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
00775                                             MAXIMUM_ALLOWED_ACCESS,
00776                                             user_rids[0], &user_pol);
00777 
00778                 if (!NT_STATUS_IS_OK(result)) {
00779                         goto done;
00780                 }
00781         }
00782 
00783         /* Delete user */
00784 
00785         result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
00786 
00787         if (!NT_STATUS_IS_OK(result)) {
00788                 goto done;
00789         }
00790 
00791         /* Display results */
00792         if (!NT_STATUS_IS_OK(result)) {
00793                 d_fprintf(stderr, "Failed to delete user account - %s\n", nt_errstr(result));
00794         } else {
00795                 d_printf("Deleted user account\n");
00796         }
00797 
00798  done:
00799         return result;
00800 }
00801 
00802 /** 
00803  * Rename a user on a remote RPC server
00804  *
00805  * All parameters are provided by the run_rpc_command function, except for
00806  * argc, argv which are passes through. 
00807  *
00808  * @param domain_sid The domain sid acquired from the remote server
00809  * @param cli A cli_state connected to the server.
00810  * @param mem_ctx Talloc context, destoyed on completion of the function.
00811  * @param argc  Standard main() style argc
00812  * @param argv  Standard main() style argv.  Initial components are already
00813  *              stripped
00814  *
00815  * @return Normal NTSTATUS return.
00816  **/
00817 
00818 static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid,
00819                                         const char *domain_name, 
00820                                         struct cli_state *cli,
00821                                         struct rpc_pipe_client *pipe_hnd,
00822                                         TALLOC_CTX *mem_ctx, 
00823                                         int argc,
00824                                         const char **argv)
00825 {
00826         POLICY_HND connect_pol, domain_pol, user_pol;
00827         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00828         uint32 info_level = 7;
00829         const char *old_name, *new_name;
00830         uint32 *user_rid;
00831         uint32 flags = 0x000003e8; /* Unknown */
00832         uint32 num_rids, *name_types;
00833         uint32 num_names = 1;
00834         const char **names;
00835         SAM_USERINFO_CTR *user_ctr;
00836         SAM_USERINFO_CTR ctr;
00837         SAM_USER_INFO_7 info7;
00838 
00839         if (argc != 2) {
00840                 d_printf("Old and new username must be specified\n");
00841                 rpc_user_usage(argc, argv);
00842                 return NT_STATUS_OK;
00843         }
00844 
00845         old_name = argv[0];
00846         new_name = argv[1];
00847 
00848         ZERO_STRUCT(ctr);
00849         ZERO_STRUCT(user_ctr);
00850 
00851         /* Get sam policy handle */
00852         
00853         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
00854                                   &connect_pol);
00855         if (!NT_STATUS_IS_OK(result)) {
00856                 goto done;
00857         }
00858         
00859         /* Get domain policy handle */
00860         
00861         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
00862                                       MAXIMUM_ALLOWED_ACCESS,
00863                                       domain_sid, &domain_pol);
00864         if (!NT_STATUS_IS_OK(result)) {
00865                 goto done;
00866         }
00867 
00868         if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
00869                 result = NT_STATUS_NO_MEMORY;
00870                 goto done;
00871         }
00872         names[0] = old_name;
00873         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
00874                                        flags, num_names, names,
00875                                        &num_rids, &user_rid, &name_types);
00876         if (!NT_STATUS_IS_OK(result)) {
00877                 goto done;
00878         }
00879 
00880         /* Open domain user */
00881         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
00882                                     MAXIMUM_ALLOWED_ACCESS, user_rid[0], &user_pol);
00883 
00884         if (!NT_STATUS_IS_OK(result)) {
00885                 goto done;
00886         }
00887 
00888         /* Query user info */
00889         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
00890                                          info_level, &user_ctr);
00891 
00892         if (!NT_STATUS_IS_OK(result)) {
00893                 goto done;
00894         }
00895 
00896         ctr.switch_value = info_level;
00897         ctr.info.id7 = &info7;
00898 
00899         init_sam_user_info7(&info7, new_name);
00900 
00901         /* Set new name */
00902         result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol,
00903                                        info_level, &cli->user_session_key, &ctr);
00904 
00905         if (!NT_STATUS_IS_OK(result)) {
00906                 goto done;
00907         }
00908 
00909  done:
00910         if (!NT_STATUS_IS_OK(result)) {
00911                 d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n", old_name, new_name, 
00912                          nt_errstr(result));
00913         } else {
00914                 d_printf("Renamed user from %s to %s\n", old_name, new_name);
00915         }
00916         return result;
00917 }
00918 
00919 /** 
00920  * Rename a user on a remote RPC server
00921  *
00922  * @param argc  Standard main() style argc
00923  * @param argv  Standard main() style argv.  Initial components are already
00924  *              stripped
00925  *
00926  * @return A shell status integer (0 for success)
00927  **/
00928 
00929 static int rpc_user_rename(int argc, const char **argv) 
00930 {
00931         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_rename_internals,
00932                                argc, argv);
00933 }
00934 
00935 /** 
00936  * Delete a user from a remote RPC server
00937  *
00938  * @param argc  Standard main() style argc
00939  * @param argv  Standard main() style argv.  Initial components are already
00940  *              stripped
00941  *
00942  * @return A shell status integer (0 for success)
00943  **/
00944 
00945 static int rpc_user_delete(int argc, const char **argv) 
00946 {
00947         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_del_internals,
00948                                argc, argv);
00949 }
00950 
00951 /** 
00952  * Set a password for a user on a remote RPC server
00953  *
00954  * All parameters are provided by the run_rpc_command function, except for
00955  * argc, argv which are passes through. 
00956  *
00957  * @param domain_sid The domain sid acquired from the remote server
00958  * @param cli A cli_state connected to the server.
00959  * @param mem_ctx Talloc context, destoyed on completion of the function.
00960  * @param argc  Standard main() style argc
00961  * @param argv  Standard main() style argv.  Initial components are already
00962  *              stripped
00963  *
00964  * @return Normal NTSTATUS return.
00965  **/
00966 
00967 static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, 
00968                                         const char *domain_name, 
00969                                         struct cli_state *cli, 
00970                                         struct rpc_pipe_client *pipe_hnd,
00971                                         TALLOC_CTX *mem_ctx, 
00972                                         int argc,
00973                                         const char **argv)
00974 {
00975         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00976         POLICY_HND connect_pol, domain_pol, user_pol;
00977         SAM_USERINFO_CTR ctr;
00978         SAM_USER_INFO_24 p24;
00979         uchar pwbuf[516];
00980         const char *user;
00981         const char *new_password;
00982         char *prompt = NULL;
00983 
00984         if (argc < 1) {
00985                 d_printf("User must be specified\n");
00986                 rpc_user_usage(argc, argv);
00987                 return NT_STATUS_OK;
00988         }
00989         
00990         user = argv[0];
00991 
00992         if (argv[1]) {
00993                 new_password = argv[1];
00994         } else {
00995                 asprintf(&prompt, "Enter new password for %s:", user);
00996                 new_password = getpass(prompt);
00997                 SAFE_FREE(prompt);
00998         }
00999 
01000         /* Get sam policy and domain handles */
01001 
01002         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
01003                                   &connect_pol);
01004 
01005         if (!NT_STATUS_IS_OK(result)) {
01006                 goto done;
01007         }
01008 
01009         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
01010                                       MAXIMUM_ALLOWED_ACCESS,
01011                                       domain_sid, &domain_pol);
01012 
01013         if (!NT_STATUS_IS_OK(result)) {
01014                 goto done;
01015         }
01016 
01017         /* Get handle on user */
01018 
01019         {
01020                 uint32 *user_rids, num_rids, *name_types;
01021                 uint32 flags = 0x000003e8; /* Unknown */
01022 
01023                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
01024                                                flags, 1, &user,
01025                                                &num_rids, &user_rids,
01026                                                &name_types);
01027 
01028                 if (!NT_STATUS_IS_OK(result)) {
01029                         goto done;
01030                 }
01031 
01032                 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
01033                                             MAXIMUM_ALLOWED_ACCESS,
01034                                             user_rids[0], &user_pol);
01035 
01036                 if (!NT_STATUS_IS_OK(result)) {
01037                         goto done;
01038                 }
01039         }
01040 
01041         /* Set password on account */
01042 
01043         ZERO_STRUCT(ctr);
01044         ZERO_STRUCT(p24);
01045 
01046         encode_pw_buffer(pwbuf, new_password, STR_UNICODE);
01047 
01048         init_sam_user_info24(&p24, (char *)pwbuf,24);
01049 
01050         ctr.switch_value = 24;
01051         ctr.info.id24 = &p24;
01052 
01053         result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 
01054                                        &cli->user_session_key, &ctr);
01055 
01056         if (!NT_STATUS_IS_OK(result)) {
01057                 goto done;
01058         }
01059 
01060         /* Display results */
01061 
01062  done:
01063         return result;
01064 
01065 }       
01066 
01067 /** 
01068  * Set a user's password on a remote RPC server
01069  *
01070  * @param argc  Standard main() style argc
01071  * @param argv  Standard main() style argv.  Initial components are already
01072  *              stripped
01073  *
01074  * @return A shell status integer (0 for success)
01075  **/
01076 
01077 static int rpc_user_password(int argc, const char **argv) 
01078 {
01079         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_password_internals,
01080                                argc, argv);
01081 }
01082 
01083 /** 
01084  * List user's groups on a remote RPC server
01085  *
01086  * All parameters are provided by the run_rpc_command function, except for
01087  * argc, argv which are passes through. 
01088  *
01089  * @param domain_sid The domain sid acquired from the remote server
01090  * @param cli A cli_state connected to the server.
01091  * @param mem_ctx Talloc context, destoyed on completion of the function.
01092  * @param argc  Standard main() style argc
01093  * @param argv  Standard main() style argv.  Initial components are already
01094  *              stripped
01095  *
01096  * @return Normal NTSTATUS return.
01097  **/
01098 
01099 static NTSTATUS rpc_user_info_internals(const DOM_SID *domain_sid,
01100                         const char *domain_name, 
01101                         struct cli_state *cli,
01102                         struct rpc_pipe_client *pipe_hnd,
01103                         TALLOC_CTX *mem_ctx,
01104                         int argc,
01105                         const char **argv)
01106 {
01107         POLICY_HND connect_pol, domain_pol, user_pol;
01108         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01109         uint32 *rids, num_rids, *name_types, num_names;
01110         uint32 flags = 0x000003e8; /* Unknown */
01111         int i;
01112         char **names;
01113         DOM_GID *user_gids;
01114 
01115         if (argc < 1) {
01116                 d_printf("User must be specified\n");
01117                 rpc_user_usage(argc, argv);
01118                 return NT_STATUS_OK;
01119         }
01120         /* Get sam policy handle */
01121         
01122         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
01123                                   &connect_pol);
01124         if (!NT_STATUS_IS_OK(result)) goto done;
01125         
01126         /* Get domain policy handle */
01127         
01128         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
01129                                       MAXIMUM_ALLOWED_ACCESS,
01130                                       domain_sid, &domain_pol);
01131         if (!NT_STATUS_IS_OK(result)) goto done;
01132 
01133         /* Get handle on user */
01134 
01135         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
01136                                        flags, 1, &argv[0],
01137                                        &num_rids, &rids, &name_types);
01138 
01139         if (!NT_STATUS_IS_OK(result)) goto done;
01140 
01141         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
01142                                     MAXIMUM_ALLOWED_ACCESS,
01143                                     rids[0], &user_pol);
01144         if (!NT_STATUS_IS_OK(result)) goto done;
01145 
01146         result = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, &user_pol,
01147                                            &num_rids, &user_gids);
01148 
01149         if (!NT_STATUS_IS_OK(result)) goto done;
01150 
01151         /* Look up rids */
01152 
01153         if (num_rids) {
01154                 if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
01155                         result = NT_STATUS_NO_MEMORY;
01156                         goto done;
01157                 }
01158 
01159                 for (i = 0; i < num_rids; i++)
01160                         rids[i] = user_gids[i].g_rid;
01161 
01162                 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, &domain_pol,
01163                                               num_rids, rids,
01164                                               &num_names, &names, &name_types);
01165 
01166                 if (!NT_STATUS_IS_OK(result)) {
01167                         goto done;
01168                 }
01169 
01170                 /* Display results */
01171 
01172                 for (i = 0; i < num_names; i++)
01173                         printf("%s\n", names[i]);
01174         }
01175  done:
01176         return result;
01177 }
01178 
01179 /** 
01180  * List a user's groups from a remote RPC server
01181  *
01182  * @param argc  Standard main() style argc
01183  * @param argv  Standard main() style argv.  Initial components are already
01184  *              stripped
01185  *
01186  * @return A shell status integer (0 for success)
01187  **/
01188 
01189 static int rpc_user_info(int argc, const char **argv) 
01190 {
01191         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_info_internals,
01192                                argc, argv);
01193 }
01194 
01195 /** 
01196  * List users on a remote RPC server
01197  *
01198  * All parameters are provided by the run_rpc_command function, except for
01199  * argc, argv which are passes through. 
01200  *
01201  * @param domain_sid The domain sid acquired from the remote server
01202  * @param cli A cli_state connected to the server.
01203  * @param mem_ctx Talloc context, destoyed on completion of the function.
01204  * @param argc  Standard main() style argc
01205  * @param argv  Standard main() style argv.  Initial components are already
01206  *              stripped
01207  *
01208  * @return Normal NTSTATUS return.
01209  **/
01210 
01211 static NTSTATUS rpc_user_list_internals(const DOM_SID *domain_sid,
01212                                         const char *domain_name, 
01213                                         struct cli_state *cli,
01214                                         struct rpc_pipe_client *pipe_hnd,
01215                                         TALLOC_CTX *mem_ctx,
01216                                         int argc,
01217                                         const char **argv)
01218 {
01219         POLICY_HND connect_pol, domain_pol;
01220         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01221         uint32 start_idx=0, num_entries, i, loop_count = 0;
01222         SAM_DISPINFO_CTR ctr;
01223         SAM_DISPINFO_1 info1;
01224 
01225         /* Get sam policy handle */
01226         
01227         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
01228                                   &connect_pol);
01229         if (!NT_STATUS_IS_OK(result)) {
01230                 goto done;
01231         }
01232         
01233         /* Get domain policy handle */
01234         
01235         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
01236                                       MAXIMUM_ALLOWED_ACCESS,
01237                                       domain_sid, &domain_pol);
01238         if (!NT_STATUS_IS_OK(result)) {
01239                 goto done;
01240         }
01241 
01242         /* Query domain users */
01243         ZERO_STRUCT(ctr);
01244         ZERO_STRUCT(info1);
01245         ctr.sam.info1 = &info1;
01246         if (opt_long_list_entries)
01247                 d_printf("\nUser name             Comment"\
01248                          "\n-----------------------------\n");
01249         do {
01250                 fstring user, desc;
01251                 uint32 max_entries, max_size;
01252 
01253                 get_query_dispinfo_params(
01254                         loop_count, &max_entries, &max_size);
01255 
01256                 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
01257                                                  &start_idx, 1, &num_entries,
01258                                                  max_entries, max_size, &ctr);
01259                 loop_count++;
01260 
01261                 for (i = 0; i < num_entries; i++) {
01262                         unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
01263                         if (opt_long_list_entries) 
01264                                 unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
01265                         
01266                         if (opt_long_list_entries)
01267                                 printf("%-21.21s %s\n", user, desc);
01268                         else
01269                                 printf("%s\n", user);
01270                 }
01271         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
01272 
01273  done:
01274         return result;
01275 }
01276 
01277 /** 
01278  * 'net rpc user' entrypoint.
01279  * @param argc  Standard main() style argc
01280  * @param argc  Standard main() style argv.  Initial components are already
01281  *              stripped
01282  **/
01283 
01284 int net_rpc_user(int argc, const char **argv) 
01285 {
01286         struct functable func[] = {
01287                 {"add", rpc_user_add},
01288                 {"info", rpc_user_info},
01289                 {"delete", rpc_user_delete},
01290                 {"password", rpc_user_password},
01291                 {"rename", rpc_user_rename},
01292                 {NULL, NULL}
01293         };
01294         
01295         if (argc == 0) {
01296                 return run_rpc_command(NULL,PI_SAMR, 0, 
01297                                        rpc_user_list_internals,
01298                                        argc, argv);
01299         }
01300 
01301         return net_run_function(argc, argv, func, rpc_user_usage);
01302 }
01303 
01304 static NTSTATUS rpc_sh_user_list(TALLOC_CTX *mem_ctx,
01305                                  struct rpc_sh_ctx *ctx,
01306                                  struct rpc_pipe_client *pipe_hnd,
01307                                  int argc, const char **argv)
01308 {
01309         return rpc_user_list_internals(ctx->domain_sid, ctx->domain_name,
01310                                        ctx->cli, pipe_hnd, mem_ctx,
01311                                        argc, argv);
01312 }
01313 
01314 static NTSTATUS rpc_sh_user_info(TALLOC_CTX *mem_ctx,
01315                                  struct rpc_sh_ctx *ctx,
01316                                  struct rpc_pipe_client *pipe_hnd,
01317                                  int argc, const char **argv)
01318 {
01319         return rpc_user_info_internals(ctx->domain_sid, ctx->domain_name,
01320                                        ctx->cli, pipe_hnd, mem_ctx,
01321                                        argc, argv);
01322 }
01323 
01324 static NTSTATUS rpc_sh_handle_user(TALLOC_CTX *mem_ctx,
01325                                    struct rpc_sh_ctx *ctx,
01326                                    struct rpc_pipe_client *pipe_hnd,
01327                                    int argc, const char **argv,
01328                                    NTSTATUS (*fn)(
01329                                            TALLOC_CTX *mem_ctx,
01330                                            struct rpc_sh_ctx *ctx,
01331                                            struct rpc_pipe_client *pipe_hnd,
01332                                            const POLICY_HND *user_hnd,
01333                                            int argc, const char **argv))
01334                                            
01335 {
01336         POLICY_HND connect_pol, domain_pol, user_pol;
01337         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01338         DOM_SID sid;
01339         uint32 rid;
01340         enum lsa_SidType type;
01341 
01342         if (argc == 0) {
01343                 d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
01344                 return NT_STATUS_INVALID_PARAMETER;
01345         }
01346 
01347         ZERO_STRUCT(connect_pol);
01348         ZERO_STRUCT(domain_pol);
01349         ZERO_STRUCT(user_pol);
01350 
01351         result = net_rpc_lookup_name(mem_ctx, pipe_hnd->cli, argv[0],
01352                                      NULL, NULL, &sid, &type);
01353         if (!NT_STATUS_IS_OK(result)) {
01354                 d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
01355                           nt_errstr(result));
01356                 goto done;
01357         }
01358 
01359         if (type != SID_NAME_USER) {
01360                 d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
01361                           sid_type_lookup(type));
01362                 result = NT_STATUS_NO_SUCH_USER;
01363                 goto done;
01364         }
01365 
01366         if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
01367                 d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
01368                 result = NT_STATUS_NO_SUCH_USER;
01369                 goto done;
01370         }
01371 
01372         result = rpccli_samr_connect(pipe_hnd, mem_ctx,
01373                                      MAXIMUM_ALLOWED_ACCESS, &connect_pol);
01374         if (!NT_STATUS_IS_OK(result)) {
01375                 goto done;
01376         }
01377 
01378         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
01379                                          MAXIMUM_ALLOWED_ACCESS,
01380                                          ctx->domain_sid, &domain_pol);
01381         if (!NT_STATUS_IS_OK(result)) {
01382                 goto done;
01383         }
01384 
01385         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
01386                                        MAXIMUM_ALLOWED_ACCESS,
01387                                        rid, &user_pol);
01388         if (!NT_STATUS_IS_OK(result)) {
01389                 goto done;
01390         }
01391 
01392         result = fn(mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
01393 
01394  done:
01395         if (is_valid_policy_hnd(&user_pol)) {
01396                 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
01397         }
01398         if (is_valid_policy_hnd(&domain_pol)) {
01399                 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
01400         }
01401         if (is_valid_policy_hnd(&connect_pol)) {
01402                 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
01403         }
01404         return result;
01405 }
01406 
01407 static NTSTATUS rpc_sh_user_show_internals(TALLOC_CTX *mem_ctx,
01408                                            struct rpc_sh_ctx *ctx,
01409                                            struct rpc_pipe_client *pipe_hnd,
01410                                            const POLICY_HND *user_hnd,
01411                                            int argc, const char **argv)
01412 {
01413         NTSTATUS result;
01414         SAM_USERINFO_CTR *ctr;
01415         SAM_USER_INFO_21 *info;
01416 
01417         if (argc != 0) {
01418                 d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
01419                 return NT_STATUS_INVALID_PARAMETER;
01420         }
01421 
01422         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
01423                                             21, &ctr);
01424         if (!NT_STATUS_IS_OK(result)) {
01425                 return result;
01426         }
01427 
01428         info = ctr->info.id21;
01429 
01430         d_printf("user rid: %d, group rid: %d\n", info->user_rid,
01431                  info->group_rid);
01432 
01433         return result;
01434 }
01435 
01436 static NTSTATUS rpc_sh_user_show(TALLOC_CTX *mem_ctx,
01437                                  struct rpc_sh_ctx *ctx,
01438                                  struct rpc_pipe_client *pipe_hnd,
01439                                  int argc, const char **argv)
01440 {
01441         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
01442                                   rpc_sh_user_show_internals);
01443 }
01444 
01445 #define FETCHSTR(name, rec) \
01446 do { if (strequal(ctx->thiscmd, name)) { \
01447         oldval = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_##rec); } \
01448 } while (0);
01449 
01450 #define SETSTR(name, rec, flag) \
01451 do { if (strequal(ctx->thiscmd, name)) { \
01452         init_unistr2(&usr->uni_##rec, argv[0], UNI_STR_TERMINATE); \
01453         init_uni_hdr(&usr->hdr_##rec, &usr->uni_##rec); \
01454         usr->fields_present |= ACCT_##flag; } \
01455 } while (0);
01456 
01457 static NTSTATUS rpc_sh_user_str_edit_internals(TALLOC_CTX *mem_ctx,
01458                                                struct rpc_sh_ctx *ctx,
01459                                                struct rpc_pipe_client *pipe_hnd,
01460                                                const POLICY_HND *user_hnd,
01461                                                int argc, const char **argv)
01462 {
01463         NTSTATUS result;
01464         SAM_USERINFO_CTR *ctr;
01465         SAM_USER_INFO_21 *usr;
01466         const char *username;
01467         const char *oldval = "";
01468 
01469         if (argc > 1) {
01470                 d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
01471                           ctx->whoami);
01472                 return NT_STATUS_INVALID_PARAMETER;
01473         }
01474 
01475         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
01476                                             21, &ctr);
01477         if (!NT_STATUS_IS_OK(result)) {
01478                 return result;
01479         }
01480 
01481         usr = ctr->info.id21;
01482 
01483         username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
01484 
01485         FETCHSTR("fullname", full_name);
01486         FETCHSTR("homedir", home_dir);
01487         FETCHSTR("homedrive", dir_drive);
01488         FETCHSTR("logonscript", logon_script);
01489         FETCHSTR("profilepath", profile_path);
01490         FETCHSTR("description", acct_desc);
01491 
01492         if (argc == 0) {
01493                 d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
01494                 goto done;
01495         }
01496 
01497         ZERO_STRUCTP(usr);
01498 
01499         if (strcmp(argv[0], "NULL") == 0) {
01500                 argv[0] = "";
01501         }
01502 
01503         SETSTR("fullname", full_name, FULL_NAME);
01504         SETSTR("homedir", home_dir, HOME_DIR);
01505         SETSTR("homedrive", dir_drive, HOME_DRIVE);
01506         SETSTR("logonscript", logon_script, LOGON_SCRIPT);
01507         SETSTR("profilepath", profile_path, PROFILE);
01508         SETSTR("description", acct_desc, DESCRIPTION);
01509 
01510         result = rpccli_samr_set_userinfo2(
01511                 pipe_hnd, mem_ctx, user_hnd, 21,
01512                 &pipe_hnd->cli->user_session_key, ctr);
01513 
01514         d_printf("Set %s's %s from [%s] to [%s]\n", username,
01515                  ctx->thiscmd, oldval, argv[0]);
01516 
01517  done:
01518 
01519         return result;
01520 }
01521 
01522 #define HANDLEFLG(name, rec) \
01523 do { if (strequal(ctx->thiscmd, name)) { \
01524         oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
01525         if (newval) { \
01526                 newflags = oldflags | ACB_##rec; \
01527         } else { \
01528                 newflags = oldflags & ~ACB_##rec; \
01529         } } } while (0);
01530 
01531 static NTSTATUS rpc_sh_user_str_edit(TALLOC_CTX *mem_ctx,
01532                                      struct rpc_sh_ctx *ctx,
01533                                      struct rpc_pipe_client *pipe_hnd,
01534                                      int argc, const char **argv)
01535 {
01536         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
01537                                   rpc_sh_user_str_edit_internals);
01538 }
01539 
01540 static NTSTATUS rpc_sh_user_flag_edit_internals(TALLOC_CTX *mem_ctx,
01541                                                 struct rpc_sh_ctx *ctx,
01542                                                 struct rpc_pipe_client *pipe_hnd,
01543                                                 const POLICY_HND *user_hnd,
01544                                                 int argc, const char **argv)
01545 {
01546         NTSTATUS result;
01547         SAM_USERINFO_CTR *ctr;
01548         SAM_USER_INFO_21 *usr;
01549         const char *username;
01550         const char *oldval = "unknown";
01551         uint32 oldflags, newflags;
01552         BOOL newval;
01553 
01554         if ((argc > 1) ||
01555             ((argc == 1) && !strequal(argv[0], "yes") &&
01556              !strequal(argv[0], "no"))) {
01557                 d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
01558                           ctx->whoami);
01559                 return NT_STATUS_INVALID_PARAMETER;
01560         }
01561 
01562         newval = strequal(argv[0], "yes");
01563 
01564         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
01565                                             21, &ctr);
01566         if (!NT_STATUS_IS_OK(result)) {
01567                 return result;
01568         }
01569 
01570         usr = ctr->info.id21;
01571 
01572         username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
01573         oldflags = usr->acb_info;
01574         newflags = usr->acb_info;
01575 
01576         HANDLEFLG("disabled", DISABLED);
01577         HANDLEFLG("pwnotreq", PWNOTREQ);
01578         HANDLEFLG("autolock", AUTOLOCK);
01579         HANDLEFLG("pwnoexp", PWNOEXP);
01580 
01581         if (argc == 0) {
01582                 d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
01583                 goto done;
01584         }
01585 
01586         ZERO_STRUCTP(usr);
01587 
01588         usr->acb_info = newflags;
01589         usr->fields_present = ACCT_FLAGS;
01590 
01591         result = rpccli_samr_set_userinfo2(
01592                 pipe_hnd, mem_ctx, user_hnd, 21,
01593                 &pipe_hnd->cli->user_session_key, ctr);
01594 
01595         if (NT_STATUS_IS_OK(result)) {
01596                 d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
01597                          ctx->thiscmd, oldval, argv[0]);
01598         }
01599 
01600  done:
01601 
01602         return result;
01603 }
01604 
01605 static NTSTATUS rpc_sh_user_flag_edit(TALLOC_CTX *mem_ctx,
01606                                       struct rpc_sh_ctx *ctx,
01607                                       struct rpc_pipe_client *pipe_hnd,
01608                                       int argc, const char **argv)
01609 {
01610         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
01611                                   rpc_sh_user_flag_edit_internals);
01612 }
01613 
01614 struct rpc_sh_cmd *net_rpc_user_edit_cmds(TALLOC_CTX *mem_ctx,
01615                                           struct rpc_sh_ctx *ctx)
01616 {
01617         static struct rpc_sh_cmd cmds[] = {
01618 
01619                 { "fullname", NULL, PI_SAMR, rpc_sh_user_str_edit,
01620                   "Show/Set a user's full name" },
01621 
01622                 { "homedir", NULL, PI_SAMR, rpc_sh_user_str_edit,
01623                   "Show/Set a user's home directory" },
01624 
01625                 { "homedrive", NULL, PI_SAMR, rpc_sh_user_str_edit,
01626                   "Show/Set a user's home drive" },
01627 
01628                 { "logonscript", NULL, PI_SAMR, rpc_sh_user_str_edit,
01629                   "Show/Set a user's logon script" },
01630 
01631                 { "profilepath", NULL, PI_SAMR, rpc_sh_user_str_edit,
01632                   "Show/Set a user's profile path" },
01633 
01634                 { "description", NULL, PI_SAMR, rpc_sh_user_str_edit,
01635                   "Show/Set a user's description" },
01636 
01637                 { "disabled", NULL, PI_SAMR, rpc_sh_user_flag_edit,
01638                   "Show/Set whether a user is disabled" },
01639 
01640                 { "autolock", NULL, PI_SAMR, rpc_sh_user_flag_edit,
01641                   "Show/Set whether a user locked out" },
01642 
01643                 { "pwnotreq", NULL, PI_SAMR, rpc_sh_user_flag_edit,
01644                   "Show/Set whether a user does not need a password" },
01645 
01646                 { "pwnoexp", NULL, PI_SAMR, rpc_sh_user_flag_edit,
01647                   "Show/Set whether a user's password does not expire" },
01648 
01649                 { NULL, NULL, 0, NULL, NULL }
01650         };
01651 
01652         return cmds;
01653 }
01654 
01655 struct rpc_sh_cmd *net_rpc_user_cmds(TALLOC_CTX *mem_ctx,
01656                                      struct rpc_sh_ctx *ctx)
01657 {
01658         static struct rpc_sh_cmd cmds[] = {
01659 
01660                 { "list", NULL, PI_SAMR, rpc_sh_user_list,
01661                   "List available users" },
01662 
01663                 { "info", NULL, PI_SAMR, rpc_sh_user_info,
01664                   "List the domain groups a user is member of" },
01665 
01666                 { "show", NULL, PI_SAMR, rpc_sh_user_show,
01667                   "Show info about a user" },
01668 
01669                 { "edit", net_rpc_user_edit_cmds, 0, NULL, 
01670                   "Show/Modify a user's fields" },
01671 
01672                 { NULL, NULL, 0, NULL, NULL }
01673         };
01674 
01675         return cmds;
01676 }
01677 
01678 /****************************************************************************/
01679 
01680 /**
01681  * Basic usage function for 'net rpc group'
01682  * @param argc  Standard main() style argc.
01683  * @param argv  Standard main() style argv.  Initial components are already
01684  *              stripped.
01685  **/
01686 
01687 static int rpc_group_usage(int argc, const char **argv)
01688 {
01689         return net_help_group(argc, argv);
01690 }
01691 
01692 /**
01693  * Delete group on a remote RPC server
01694  *
01695  * All parameters are provided by the run_rpc_command function, except for
01696  * argc, argv which are passes through.
01697  *
01698  * @param domain_sid The domain sid acquired from the remote server
01699  * @param cli A cli_state connected to the server.
01700  * @param mem_ctx Talloc context, destoyed on completion of the function.
01701  * @param argc  Standard main() style argc
01702  * @param argv  Standard main() style argv.  Initial components are already
01703  *              stripped
01704  *
01705  * @return Normal NTSTATUS return.
01706  **/
01707                                                                                                              
01708 static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
01709                                         const char *domain_name,
01710                                         struct cli_state *cli,
01711                                         struct rpc_pipe_client *pipe_hnd,
01712                                         TALLOC_CTX *mem_ctx,
01713                                         int argc,
01714                                         const char **argv)
01715 {
01716         POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
01717         BOOL group_is_primary = False;
01718         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01719 
01720         uint32 *group_rids, num_rids, *name_types, num_members, 
01721                *group_attrs, group_rid;
01722         uint32 flags = 0x000003e8; /* Unknown */
01723         /* char **names; */
01724         int i;
01725         /* DOM_GID *user_gids; */
01726         SAM_USERINFO_CTR *user_ctr;
01727         fstring temp;
01728 
01729         if (argc < 1) {
01730                 d_printf("specify group\n");
01731                 rpc_group_usage(argc,argv);
01732                 return NT_STATUS_OK; /* ok? */
01733         }
01734 
01735         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
01736                                   &connect_pol);
01737 
01738         if (!NT_STATUS_IS_OK(result)) {
01739                 d_fprintf(stderr, "Request samr_connect failed\n");
01740                 goto done;
01741         }
01742         
01743         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
01744                                       MAXIMUM_ALLOWED_ACCESS,
01745                                       domain_sid, &domain_pol);
01746         
01747         if (!NT_STATUS_IS_OK(result)) {
01748                 d_fprintf(stderr, "Request open_domain failed\n");
01749                 goto done;
01750         }
01751         
01752         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
01753                                        flags, 1, &argv[0],
01754                                        &num_rids, &group_rids,
01755                                        &name_types);
01756 
01757         if (!NT_STATUS_IS_OK(result)) {
01758                 d_fprintf(stderr, "Lookup of '%s' failed\n",argv[0]);
01759                 goto done;
01760         }
01761 
01762         switch (name_types[0])
01763         {
01764         case SID_NAME_DOM_GRP:
01765                 result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
01766                                              MAXIMUM_ALLOWED_ACCESS,
01767                                              group_rids[0], &group_pol);
01768                 if (!NT_STATUS_IS_OK(result)) {
01769                         d_fprintf(stderr, "Request open_group failed");
01770                         goto done;
01771                 }
01772                 
01773                 group_rid = group_rids[0];
01774                 
01775                 result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
01776                                  &num_members, &group_rids,
01777                                  &group_attrs);
01778                 
01779                 if (!NT_STATUS_IS_OK(result)) {
01780                         d_fprintf(stderr, "Unable to query group members of %s",argv[0]);
01781                         goto done;
01782                 }
01783                 
01784                 if (opt_verbose) {
01785                         d_printf("Domain Group %s (rid: %d) has %d members\n",
01786                                 argv[0],group_rid,num_members);
01787                 }
01788 
01789                 /* Check if group is anyone's primary group */
01790                 for (i = 0; i < num_members; i++)
01791                 {
01792                         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
01793                                                     MAXIMUM_ALLOWED_ACCESS,
01794                                                     group_rids[i], &user_pol);
01795         
01796                         if (!NT_STATUS_IS_OK(result)) {
01797                                 d_fprintf(stderr, "Unable to open group member %d\n",group_rids[i]);
01798                                 goto done;
01799                         }
01800         
01801                         ZERO_STRUCT(user_ctr);
01802 
01803                         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
01804                                                          21, &user_ctr);
01805         
01806                         if (!NT_STATUS_IS_OK(result)) {
01807                                 d_fprintf(stderr, "Unable to lookup userinfo for group member %d\n",group_rids[i]);
01808                                 goto done;
01809                         }
01810         
01811                         if (user_ctr->info.id21->group_rid == group_rid) {
01812                                 unistr2_to_ascii(temp, &(user_ctr->info.id21)->uni_user_name, 
01813                                                 sizeof(temp)-1);
01814                                 if (opt_verbose) 
01815                                         d_printf("Group is primary group of %s\n",temp);
01816                                 group_is_primary = True;
01817                         }
01818 
01819                         rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
01820                 }
01821                 
01822                 if (group_is_primary) {
01823                         d_fprintf(stderr, "Unable to delete group because some "
01824                                  "of it's members have it as primary group\n");
01825                         result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
01826                         goto done;
01827                 }
01828      
01829                 /* remove all group members */
01830                 for (i = 0; i < num_members; i++)
01831                 {
01832                         if (opt_verbose) 
01833                                 d_printf("Remove group member %d...",group_rids[i]);
01834                         result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, group_rids[i]);
01835 
01836                         if (NT_STATUS_IS_OK(result)) {
01837                                 if (opt_verbose)
01838                                         d_printf("ok\n");
01839                         } else {
01840                                 if (opt_verbose)
01841                                         d_printf("failed\n");
01842                                 goto done;
01843                         }       
01844                 }
01845 
01846                 result = rpccli_samr_delete_dom_group(pipe_hnd, mem_ctx, &group_pol);
01847 
01848                 break;
01849         /* removing a local group is easier... */
01850         case SID_NAME_ALIAS:
01851                 result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
01852                                              MAXIMUM_ALLOWED_ACCESS,
01853                                              group_rids[0], &group_pol);
01854 
01855                 if (!NT_STATUS_IS_OK(result)) {
01856                         d_fprintf(stderr, "Request open_alias failed\n");
01857                         goto done;
01858                 }
01859                 
01860                 result = rpccli_samr_delete_dom_alias(pipe_hnd, mem_ctx, &group_pol);
01861                 break;
01862         default:
01863                 d_fprintf(stderr, "%s is of type %s. This command is only for deleting local or global groups\n",
01864                         argv[0],sid_type_lookup(name_types[0]));
01865                 result = NT_STATUS_UNSUCCESSFUL;
01866                 goto done;
01867         }
01868          
01869         
01870         if (NT_STATUS_IS_OK(result)) {
01871                 if (opt_verbose)
01872                         d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types[0]),argv[0]);
01873         } else {
01874                 d_fprintf(stderr, "Deleting of %s failed: %s\n",argv[0],
01875                         get_friendly_nt_error_msg(result));
01876         }
01877         
01878  done:
01879         return result;  
01880         
01881 }
01882 
01883 static int rpc_group_delete(int argc, const char **argv)
01884 {
01885         return run_rpc_command(NULL, PI_SAMR, 0, rpc_group_delete_internals,
01886                                argc,argv);
01887 }
01888 
01889 static NTSTATUS rpc_group_add_internals(const DOM_SID *domain_sid,
01890                                         const char *domain_name, 
01891                                         struct cli_state *cli,
01892                                         struct rpc_pipe_client *pipe_hnd,
01893                                         TALLOC_CTX *mem_ctx,
01894                                         int argc,
01895                                         const char **argv)
01896 {
01897         POLICY_HND connect_pol, domain_pol, group_pol;
01898         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01899         GROUP_INFO_CTR group_info;
01900 
01901         if (argc != 1) {
01902                 d_printf("Group name must be specified\n");
01903                 rpc_group_usage(argc, argv);
01904                 return NT_STATUS_OK;
01905         }
01906 
01907         /* Get sam policy handle */
01908         
01909         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
01910                                   &connect_pol);
01911         if (!NT_STATUS_IS_OK(result)) goto done;
01912         
01913         /* Get domain policy handle */
01914         
01915         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
01916                                       MAXIMUM_ALLOWED_ACCESS,
01917                                       domain_sid, &domain_pol);
01918         if (!NT_STATUS_IS_OK(result)) goto done;
01919 
01920         /* Create the group */
01921 
01922         result = rpccli_samr_create_dom_group(pipe_hnd, mem_ctx, &domain_pol,
01923                                            argv[0], MAXIMUM_ALLOWED_ACCESS,
01924                                            &group_pol);
01925         if (!NT_STATUS_IS_OK(result)) goto done;
01926 
01927         if (strlen(opt_comment) == 0) goto done;
01928 
01929         /* We've got a comment to set */
01930 
01931         group_info.switch_value1 = 4;
01932         init_samr_group_info4(&group_info.group.info4, opt_comment);
01933 
01934         result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &group_info);
01935         if (!NT_STATUS_IS_OK(result)) goto done;
01936         
01937  done:
01938         if (NT_STATUS_IS_OK(result))
01939                 DEBUG(5, ("add group succeeded\n"));
01940         else
01941                 d_fprintf(stderr, "add group failed: %s\n", nt_errstr(result));
01942 
01943         return result;
01944 }
01945 
01946 static NTSTATUS rpc_alias_add_internals(const DOM_SID *domain_sid,
01947                                         const char *domain_name, 
01948                                         struct cli_state *cli,
01949                                         struct rpc_pipe_client *pipe_hnd,
01950                                         TALLOC_CTX *mem_ctx,
01951                                         int argc,
01952                                         const char **argv)
01953 {
01954         POLICY_HND connect_pol, domain_pol, alias_pol;
01955         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01956         ALIAS_INFO_CTR alias_info;
01957 
01958         if (argc != 1) {
01959                 d_printf("Alias name must be specified\n");
01960                 rpc_group_usage(argc, argv);
01961                 return NT_STATUS_OK;
01962         }
01963 
01964         /* Get sam policy handle */
01965         
01966         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
01967                                   &connect_pol);
01968         if (!NT_STATUS_IS_OK(result)) goto done;
01969         
01970         /* Get domain policy handle */
01971         
01972         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
01973                                       MAXIMUM_ALLOWED_ACCESS,
01974                                       domain_sid, &domain_pol);
01975         if (!NT_STATUS_IS_OK(result)) goto done;
01976 
01977         /* Create the group */
01978 
01979         result = rpccli_samr_create_dom_alias(pipe_hnd, mem_ctx, &domain_pol,
01980                                            argv[0], &alias_pol);
01981         if (!NT_STATUS_IS_OK(result)) goto done;
01982 
01983         if (strlen(opt_comment) == 0) goto done;
01984 
01985         /* We've got a comment to set */
01986 
01987         alias_info.level = 3;
01988         init_samr_alias_info3(&alias_info.alias.info3, opt_comment);
01989 
01990         result = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, &alias_pol, &alias_info);
01991         if (!NT_STATUS_IS_OK(result)) goto done;
01992         
01993  done:
01994         if (NT_STATUS_IS_OK(result))
01995                 DEBUG(5, ("add alias succeeded\n"));
01996         else
01997                 d_fprintf(stderr, "add alias failed: %s\n", nt_errstr(result));
01998 
01999         return result;
02000 }
02001 
02002 static int rpc_group_add(int argc, const char **argv)
02003 {
02004         if (opt_localgroup)
02005                 return run_rpc_command(NULL, PI_SAMR, 0,
02006                                        rpc_alias_add_internals,
02007                                        argc, argv);
02008 
02009         return run_rpc_command(NULL, PI_SAMR, 0,
02010                                rpc_group_add_internals,
02011                                argc, argv);
02012 }
02013 
02014 static NTSTATUS get_sid_from_name(struct cli_state *cli,
02015                                 TALLOC_CTX *mem_ctx,
02016                                 const char *name,
02017                                 DOM_SID *sid,
02018                                 enum lsa_SidType *type)
02019 {
02020         DOM_SID *sids = NULL;
02021         enum lsa_SidType *types = NULL;
02022         struct rpc_pipe_client *pipe_hnd;
02023         POLICY_HND lsa_pol;
02024         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
02025 
02026         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
02027         if (!pipe_hnd) {
02028                 goto done;
02029         }
02030 
02031         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False,
02032                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
02033 
02034         if (!NT_STATUS_IS_OK(result)) {
02035                 goto done;
02036         }
02037 
02038         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
02039                                       &name, NULL, &sids, &types);
02040 
02041         if (NT_STATUS_IS_OK(result)) {
02042                 sid_copy(sid, &sids[0]);
02043                 *type = types[0];
02044         }
02045 
02046         rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
02047 
02048  done:
02049         if (pipe_hnd) {
02050                 cli_rpc_pipe_close(pipe_hnd);
02051         }
02052 
02053         if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
02054 
02055                 /* Try as S-1-5-whatever */
02056 
02057                 DOM_SID tmp_sid;
02058 
02059                 if (string_to_sid(&tmp_sid, name)) {
02060                         sid_copy(sid, &tmp_sid);
02061                         *type = SID_NAME_UNKNOWN;
02062                         result = NT_STATUS_OK;
02063                 }
02064         }
02065 
02066         return result;
02067 }
02068 
02069 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
02070                                 TALLOC_CTX *mem_ctx,
02071                                 const DOM_SID *group_sid,
02072                                 const char *member)
02073 {
02074         POLICY_HND connect_pol, domain_pol;
02075         NTSTATUS result;
02076         uint32 group_rid;
02077         POLICY_HND group_pol;
02078 
02079         uint32 num_rids;
02080         uint32 *rids = NULL;
02081         uint32 *rid_types = NULL;
02082 
02083         DOM_SID sid;
02084 
02085         sid_copy(&sid, group_sid);
02086 
02087         if (!sid_split_rid(&sid, &group_rid)) {
02088                 return NT_STATUS_UNSUCCESSFUL;
02089         }
02090 
02091         /* Get sam policy handle */     
02092         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
02093                                   &connect_pol);
02094         if (!NT_STATUS_IS_OK(result)) {
02095                 return result;
02096         }
02097         
02098         /* Get domain policy handle */
02099         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02100                                       MAXIMUM_ALLOWED_ACCESS,
02101                                       &sid, &domain_pol);
02102         if (!NT_STATUS_IS_OK(result)) {
02103                 return result;
02104         }
02105 
02106         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
02107                                        1, &member,
02108                                        &num_rids, &rids, &rid_types);
02109 
02110         if (!NT_STATUS_IS_OK(result)) {
02111                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
02112                 goto done;
02113         }
02114 
02115         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
02116                                      MAXIMUM_ALLOWED_ACCESS,
02117                                      group_rid, &group_pol);
02118 
02119         if (!NT_STATUS_IS_OK(result)) {
02120                 goto done;
02121         }
02122 
02123         result = rpccli_samr_add_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
02124 
02125  done:
02126         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
02127         return result;
02128 }
02129 
02130 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
02131                                 TALLOC_CTX *mem_ctx,
02132                                 const DOM_SID *alias_sid,
02133                                 const char *member)
02134 {
02135         POLICY_HND connect_pol, domain_pol;
02136         NTSTATUS result;
02137         uint32 alias_rid;
02138         POLICY_HND alias_pol;
02139 
02140         DOM_SID member_sid;
02141         enum lsa_SidType member_type;
02142 
02143         DOM_SID sid;
02144 
02145         sid_copy(&sid, alias_sid);
02146 
02147         if (!sid_split_rid(&sid, &alias_rid)) {
02148                 return NT_STATUS_UNSUCCESSFUL;
02149         }
02150 
02151         result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
02152                                    &member_sid, &member_type);
02153 
02154         if (!NT_STATUS_IS_OK(result)) {
02155                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
02156                 return result;
02157         }
02158 
02159         /* Get sam policy handle */     
02160         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
02161                                   &connect_pol);
02162         if (!NT_STATUS_IS_OK(result)) {
02163                 goto done;
02164         }
02165         
02166         /* Get domain policy handle */
02167         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02168                                       MAXIMUM_ALLOWED_ACCESS,
02169                                       &sid, &domain_pol);
02170         if (!NT_STATUS_IS_OK(result)) {
02171                 goto done;
02172         }
02173 
02174         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
02175                                      MAXIMUM_ALLOWED_ACCESS,
02176                                      alias_rid, &alias_pol);
02177 
02178         if (!NT_STATUS_IS_OK(result)) {
02179                 return result;
02180         }
02181 
02182         result = rpccli_samr_add_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
02183 
02184         if (!NT_STATUS_IS_OK(result)) {
02185                 return result;
02186         }
02187 
02188  done:
02189         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
02190         return result;
02191 }
02192 
02193 static NTSTATUS rpc_group_addmem_internals(const DOM_SID *domain_sid,
02194                                         const char *domain_name, 
02195                                         struct cli_state *cli,
02196                                         struct rpc_pipe_client *pipe_hnd,
02197                                         TALLOC_CTX *mem_ctx,
02198                                         int argc,
02199                                         const char **argv)
02200 {
02201         DOM_SID group_sid;
02202         enum lsa_SidType group_type;
02203 
02204         if (argc != 2) {
02205                 d_printf("Usage: 'net rpc group addmem <group> <member>\n");
02206                 return NT_STATUS_UNSUCCESSFUL;
02207         }
02208 
02209         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
02210                                                &group_sid, &group_type))) {
02211                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
02212                 return NT_STATUS_UNSUCCESSFUL;
02213         }
02214 
02215         if (group_type == SID_NAME_DOM_GRP) {
02216                 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
02217                                                    &group_sid, argv[1]);
02218 
02219                 if (!NT_STATUS_IS_OK(result)) {
02220                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
02221                                  argv[1], argv[0], nt_errstr(result));
02222                 }
02223                 return result;
02224         }
02225 
02226         if (group_type == SID_NAME_ALIAS) {
02227                 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
02228                                                    &group_sid, argv[1]);
02229 
02230                 if (!NT_STATUS_IS_OK(result)) {
02231                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
02232                                  argv[1], argv[0], nt_errstr(result));
02233                 }
02234                 return result;
02235         }
02236 
02237         d_fprintf(stderr, "Can only add members to global or local groups "
02238                  "which %s is not\n", argv[0]);
02239 
02240         return NT_STATUS_UNSUCCESSFUL;
02241 }
02242 
02243 static int rpc_group_addmem(int argc, const char **argv)
02244 {
02245         return run_rpc_command(NULL, PI_SAMR, 0,
02246                                rpc_group_addmem_internals,
02247                                argc, argv);
02248 }
02249 
02250 static NTSTATUS rpc_del_groupmem(struct rpc_pipe_client *pipe_hnd,
02251                                 TALLOC_CTX *mem_ctx,
02252                                 const DOM_SID *group_sid,
02253                                 const char *member)
02254 {
02255         POLICY_HND connect_pol, domain_pol;
02256         NTSTATUS result;
02257         uint32 group_rid;
02258         POLICY_HND group_pol;
02259 
02260         uint32 num_rids;
02261         uint32 *rids = NULL;
02262         uint32 *rid_types = NULL;
02263 
02264         DOM_SID sid;
02265 
02266         sid_copy(&sid, group_sid);
02267 
02268         if (!sid_split_rid(&sid, &group_rid))
02269                 return NT_STATUS_UNSUCCESSFUL;
02270 
02271         /* Get sam policy handle */     
02272         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
02273                                   &connect_pol);
02274         if (!NT_STATUS_IS_OK(result))
02275                 return result;
02276         
02277         /* Get domain policy handle */
02278         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02279                                       MAXIMUM_ALLOWED_ACCESS,
02280                                       &sid, &domain_pol);
02281         if (!NT_STATUS_IS_OK(result))
02282                 return result;
02283 
02284         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
02285                                        1, &member,
02286                                        &num_rids, &rids, &rid_types);
02287 
02288         if (!NT_STATUS_IS_OK(result)) {
02289                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
02290                 goto done;
02291         }
02292 
02293         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
02294                                      MAXIMUM_ALLOWED_ACCESS,
02295                                      group_rid, &group_pol);
02296 
02297         if (!NT_STATUS_IS_OK(result))
02298                 goto done;
02299 
02300         result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
02301 
02302  done:
02303         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
02304         return result;
02305 }
02306 
02307 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
02308                                 TALLOC_CTX *mem_ctx,
02309                                 const DOM_SID *alias_sid,
02310                                 const char *member)
02311 {
02312         POLICY_HND connect_pol, domain_pol;
02313         NTSTATUS result;
02314         uint32 alias_rid;
02315         POLICY_HND alias_pol;
02316 
02317         DOM_SID member_sid;
02318         enum lsa_SidType member_type;
02319 
02320         DOM_SID sid;
02321 
02322         sid_copy(&sid, alias_sid);
02323 
02324         if (!sid_split_rid(&sid, &alias_rid))
02325                 return NT_STATUS_UNSUCCESSFUL;
02326 
02327         result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
02328                                    &member_sid, &member_type);
02329 
02330         if (!NT_STATUS_IS_OK(result)) {
02331                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
02332                 return result;
02333         }
02334 
02335         /* Get sam policy handle */     
02336         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
02337                                   &connect_pol);
02338         if (!NT_STATUS_IS_OK(result)) {
02339                 goto done;
02340         }
02341         
02342         /* Get domain policy handle */
02343         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02344                                       MAXIMUM_ALLOWED_ACCESS,
02345                                       &sid, &domain_pol);
02346         if (!NT_STATUS_IS_OK(result)) {
02347                 goto done;
02348         }
02349 
02350         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
02351                                      MAXIMUM_ALLOWED_ACCESS,
02352                                      alias_rid, &alias_pol);
02353 
02354         if (!NT_STATUS_IS_OK(result))
02355                 return result;
02356 
02357         result = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
02358 
02359         if (!NT_STATUS_IS_OK(result))
02360                 return result;
02361 
02362  done:
02363         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
02364         return result;
02365 }
02366 
02367 static NTSTATUS rpc_group_delmem_internals(const DOM_SID *domain_sid,
02368                                         const char *domain_name, 
02369                                         struct cli_state *cli,
02370                                         struct rpc_pipe_client *pipe_hnd,
02371                                         TALLOC_CTX *mem_ctx,
02372                                         int argc,
02373                                         const char **argv)
02374 {
02375         DOM_SID group_sid;
02376         enum lsa_SidType group_type;
02377 
02378         if (argc != 2) {
02379                 d_printf("Usage: 'net rpc group delmem <group> <member>\n");
02380                 return NT_STATUS_UNSUCCESSFUL;
02381         }
02382 
02383         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
02384                                                &group_sid, &group_type))) {
02385                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
02386                 return NT_STATUS_UNSUCCESSFUL;
02387         }
02388 
02389         if (group_type == SID_NAME_DOM_GRP) {
02390                 NTSTATUS result = rpc_del_groupmem(pipe_hnd, mem_ctx,
02391                                                    &group_sid, argv[1]);
02392 
02393                 if (!NT_STATUS_IS_OK(result)) {
02394                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
02395                                  argv[1], argv[0], nt_errstr(result));
02396                 }
02397                 return result;
02398         }
02399 
02400         if (group_type == SID_NAME_ALIAS) {
02401                 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx, 
02402                                                    &group_sid, argv[1]);
02403 
02404                 if (!NT_STATUS_IS_OK(result)) {
02405                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
02406                                  argv[1], argv[0], nt_errstr(result));
02407                 }
02408                 return result;
02409         }
02410 
02411         d_fprintf(stderr, "Can only delete members from global or local groups "
02412                  "which %s is not\n", argv[0]);
02413 
02414         return NT_STATUS_UNSUCCESSFUL;
02415 }
02416 
02417 static int rpc_group_delmem(int argc, const char **argv)
02418 {
02419         return run_rpc_command(NULL, PI_SAMR, 0,
02420                                rpc_group_delmem_internals,
02421                                argc, argv);
02422 }
02423 
02424 /** 
02425  * List groups on a remote RPC server
02426  *
02427  * All parameters are provided by the run_rpc_command function, except for
02428  * argc, argv which are passes through. 
02429  *
02430  * @param domain_sid The domain sid acquired from the remote server
02431  * @param cli A cli_state connected to the server.
02432  * @param mem_ctx Talloc context, destoyed on completion of the function.
02433  * @param argc  Standard main() style argc
02434  * @param argv  Standard main() style argv.  Initial components are already
02435  *              stripped
02436  *
02437  * @return Normal NTSTATUS return.
02438  **/
02439 
02440 static NTSTATUS rpc_group_list_internals(const DOM_SID *domain_sid,
02441                                         const char *domain_name, 
02442                                         struct cli_state *cli,
02443                                         struct rpc_pipe_client *pipe_hnd,
02444                                         TALLOC_CTX *mem_ctx,
02445                                         int argc,
02446                                         const char **argv)
02447 {
02448         POLICY_HND connect_pol, domain_pol;
02449         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
02450         uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
02451         struct acct_info *groups;
02452         BOOL global = False;
02453         BOOL local = False;
02454         BOOL builtin = False;
02455 
02456         if (argc == 0) {
02457                 global = True;
02458                 local = True;
02459                 builtin = True;
02460         }
02461 
02462         for (i=0; i<argc; i++) {
02463                 if (strequal(argv[i], "global"))
02464                         global = True;
02465 
02466                 if (strequal(argv[i], "local"))
02467                         local = True;
02468 
02469                 if (strequal(argv[i], "builtin"))
02470                         builtin = True;
02471         }
02472 
02473         /* Get sam policy handle */
02474         
02475         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
02476                                   &connect_pol);
02477         if (!NT_STATUS_IS_OK(result)) {
02478                 goto done;
02479         }
02480         
02481         /* Get domain policy handle */
02482         
02483         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02484                                       MAXIMUM_ALLOWED_ACCESS,
02485                                       domain_sid, &domain_pol);
02486         if (!NT_STATUS_IS_OK(result)) {
02487                 goto done;
02488         }
02489 
02490         /* Query domain groups */
02491         if (opt_long_list_entries)
02492                 d_printf("\nGroup name            Comment"\
02493                          "\n-----------------------------\n");
02494         do {
02495                 SAM_DISPINFO_CTR ctr;
02496                 SAM_DISPINFO_3 info3;
02497                 uint32 max_size;
02498 
02499                 ZERO_STRUCT(ctr);
02500                 ZERO_STRUCT(info3);
02501                 ctr.sam.info3 = &info3;
02502 
02503                 if (!global) break;
02504 
02505                 get_query_dispinfo_params(
02506                         loop_count, &max_entries, &max_size);
02507 
02508                 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
02509                                                  &start_idx, 3, &num_entries,
02510                                                  max_entries, max_size, &ctr);
02511 
02512                 if (!NT_STATUS_IS_OK(result) &&
02513                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
02514                         break;
02515                                                  
02516                 for (i = 0; i < num_entries; i++) {
02517 
02518                         fstring group, desc;
02519 
02520                         unistr2_to_ascii(group, &(&ctr.sam.info3->str[i])->uni_grp_name, sizeof(group)-1);
02521                         unistr2_to_ascii(desc, &(&ctr.sam.info3->str[i])->uni_grp_desc, sizeof(desc)-1);
02522                         
02523                         if (opt_long_list_entries)
02524                                 printf("%-21.21s %-50.50s\n",
02525                                        group, desc);
02526                         else
02527                                 printf("%s\n", group);
02528                 }
02529         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
02530         /* query domain aliases */
02531         start_idx = 0;
02532         do {
02533                 if (!local) break;
02534 
02535                 /* The max_size field in cli_samr_enum_als_groups is more like
02536                  * an account_control field with indiviual bits what to
02537                  * retrieve. Set this to 0xffff as NT4 usrmgr.exe does to get
02538                  * everything. I'm too lazy (sorry) to get this through to
02539                  * rpc_parse/ etc.  Volker */
02540 
02541                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
02542                                                   &start_idx, 0xffff,
02543                                                   &groups, &num_entries);
02544 
02545                 if (!NT_STATUS_IS_OK(result) &&
02546                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
02547                         break;
02548                                                  
02549                 for (i = 0; i < num_entries; i++) {
02550 
02551                         char *description = NULL;
02552 
02553                         if (opt_long_list_entries) {
02554 
02555                                 POLICY_HND alias_pol;
02556                                 ALIAS_INFO_CTR ctr;
02557 
02558                                 if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
02559                                                                          &domain_pol,
02560                                                                          0x8,
02561                                                                          groups[i].rid,
02562                                                                          &alias_pol))) &&
02563                                     (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
02564                                                                                &alias_pol, 3,
02565                                                                                &ctr))) &&
02566                                     (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
02567                                                                     &alias_pol)))) {
02568                                         description = unistr2_tdup(mem_ctx,
02569                                                                    ctr.alias.info3.description.string);
02570                                 }
02571                         }
02572                         
02573                         if (description != NULL) {
02574                                 printf("%-21.21s %-50.50s\n", 
02575                                        groups[i].acct_name,
02576                                        description);
02577                         } else {
02578                                 printf("%s\n", groups[i].acct_name);
02579                         }
02580                 }
02581         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
02582         rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
02583         /* Get builtin policy handle */
02584         
02585         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02586                                       MAXIMUM_ALLOWED_ACCESS,
02587                                       &global_sid_Builtin, &domain_pol);
02588         if (!NT_STATUS_IS_OK(result)) {
02589                 goto done;
02590         }
02591         /* query builtin aliases */
02592         start_idx = 0;
02593         do {
02594                 if (!builtin) break;
02595 
02596                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
02597                                                   &start_idx, max_entries,
02598                                                   &groups, &num_entries);
02599                                                  
02600                 if (!NT_STATUS_IS_OK(result) &&
02601                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
02602                         break;
02603                                                  
02604                 for (i = 0; i < num_entries; i++) {
02605 
02606                         char *description = NULL;
02607 
02608                         if (opt_long_list_entries) {
02609 
02610                                 POLICY_HND alias_pol;
02611                                 ALIAS_INFO_CTR ctr;
02612 
02613                                 if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
02614                                                                          &domain_pol,
02615                                                                          0x8,
02616                                                                          groups[i].rid,
02617                                                                          &alias_pol))) &&
02618                                     (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
02619                                                                                &alias_pol, 3,
02620                                                                                &ctr))) &&
02621                                     (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
02622                                                                     &alias_pol)))) {
02623                                         description = unistr2_tdup(mem_ctx,
02624                                                                    ctr.alias.info3.description.string);
02625                                 }
02626                         }
02627                         
02628                         if (description != NULL) {
02629                                 printf("%-21.21s %-50.50s\n", 
02630                                        groups[i].acct_name,
02631                                        description);
02632                         } else {
02633                                 printf("%s\n", groups[i].acct_name);
02634                         }
02635                 }
02636         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
02637 
02638  done:
02639         return result;
02640 }
02641 
02642 static int rpc_group_list(int argc, const char **argv)
02643 {
02644         return run_rpc_command(NULL, PI_SAMR, 0,
02645                                rpc_group_list_internals,
02646                                argc, argv);
02647 }
02648 
02649 static NTSTATUS rpc_list_group_members(struct rpc_pipe_client *pipe_hnd,
02650                                         TALLOC_CTX *mem_ctx,
02651                                         const char *domain_name,
02652                                         const DOM_SID *domain_sid,
02653                                         POLICY_HND *domain_pol,
02654                                         uint32 rid)
02655 {
02656         NTSTATUS result;
02657         POLICY_HND group_pol;
02658         uint32 num_members, *group_rids, *group_attrs;
02659         uint32 num_names;
02660         char **names;
02661         uint32 *name_types;
02662         int i;
02663 
02664         fstring sid_str;
02665         sid_to_string(sid_str, domain_sid);
02666 
02667         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, domain_pol,
02668                                      MAXIMUM_ALLOWED_ACCESS,
02669                                      rid, &group_pol);
02670 
02671         if (!NT_STATUS_IS_OK(result))
02672                 return result;
02673 
02674         result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
02675                                          &num_members, &group_rids,
02676                                          &group_attrs);
02677 
02678         if (!NT_STATUS_IS_OK(result))
02679                 return result;
02680 
02681         while (num_members > 0) {
02682                 int this_time = 512;
02683 
02684                 if (num_members < this_time)
02685                         this_time = num_members;
02686 
02687                 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, domain_pol,
02688                                               this_time, group_rids,
02689                                               &num_names, &names, &name_types);
02690 
02691                 if (!NT_STATUS_IS_OK(result))
02692                         return result;
02693 
02694                 /* We only have users as members, but make the output
02695                    the same as the output of alias members */
02696 
02697                 for (i = 0; i < this_time; i++) {
02698 
02699                         if (opt_long_list_entries) {
02700                                 printf("%s-%d %s\\%s %d\n", sid_str,
02701                                        group_rids[i], domain_name, names[i],
02702                                        SID_NAME_USER);
02703                         } else {
02704                                 printf("%s\\%s\n", domain_name, names[i]);
02705                         }
02706                 }
02707 
02708                 num_members -= this_time;
02709                 group_rids += 512;
02710         }
02711 
02712         return NT_STATUS_OK;
02713 }
02714 
02715 static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
02716                                         TALLOC_CTX *mem_ctx,
02717                                         POLICY_HND *domain_pol,
02718                                         uint32 rid)
02719 {
02720         NTSTATUS result;
02721         struct rpc_pipe_client *lsa_pipe;
02722         POLICY_HND alias_pol, lsa_pol;
02723         uint32 num_members;
02724         DOM_SID *alias_sids;
02725         char **domains;
02726         char **names;
02727         enum lsa_SidType *types;
02728         int i;
02729 
02730         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, domain_pol,
02731                                      MAXIMUM_ALLOWED_ACCESS, rid, &alias_pol);
02732 
02733         if (!NT_STATUS_IS_OK(result))
02734                 return result;
02735 
02736         result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, &alias_pol,
02737                                          &num_members, &alias_sids);
02738 
02739         if (!NT_STATUS_IS_OK(result)) {
02740                 d_fprintf(stderr, "Couldn't list alias members\n");
02741                 return result;
02742         }
02743 
02744         if (num_members == 0) {
02745                 return NT_STATUS_OK;
02746         }
02747 
02748         lsa_pipe = cli_rpc_pipe_open_noauth(pipe_hnd->cli, PI_LSARPC, &result);
02749         if (!lsa_pipe) {
02750                 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
02751                         nt_errstr(result) );
02752                 return result;
02753         }
02754 
02755         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
02756                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
02757 
02758         if (!NT_STATUS_IS_OK(result)) {
02759                 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
02760                 cli_rpc_pipe_close(lsa_pipe);
02761                 return result;
02762         }
02763 
02764         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol, num_members,
02765                                      alias_sids, 
02766                                      &domains, &names, &types);
02767 
02768         if (!NT_STATUS_IS_OK(result) &&
02769             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
02770                 d_fprintf(stderr, "Couldn't lookup SIDs\n");
02771                 cli_rpc_pipe_close(lsa_pipe);
02772                 return result;
02773         }
02774 
02775         for (i = 0; i < num_members; i++) {
02776                 fstring sid_str;
02777                 sid_to_string(sid_str, &alias_sids[i]);
02778 
02779                 if (opt_long_list_entries) {
02780                         printf("%s %s\\%s %d\n", sid_str, 
02781                                domains[i] ? domains[i] : "*unknown*", 
02782                                names[i] ? names[i] : "*unknown*", types[i]);
02783                 } else {
02784                         if (domains[i])
02785                                 printf("%s\\%s\n", domains[i], names[i]);
02786                         else
02787                                 printf("%s\n", sid_str);
02788                 }
02789         }
02790 
02791         cli_rpc_pipe_close(lsa_pipe);
02792         return NT_STATUS_OK;
02793 }
02794  
02795 static NTSTATUS rpc_group_members_internals(const DOM_SID *domain_sid,
02796                                         const char *domain_name, 
02797                                         struct cli_state *cli,
02798                                         struct rpc_pipe_client *pipe_hnd,
02799                                         TALLOC_CTX *mem_ctx,
02800                                         int argc,
02801                                         const char **argv)
02802 {
02803         NTSTATUS result;
02804         POLICY_HND connect_pol, domain_pol;
02805         uint32 num_rids, *rids, *rid_types;
02806 
02807         /* Get sam policy handle */
02808         
02809         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
02810                                   &connect_pol);
02811 
02812         if (!NT_STATUS_IS_OK(result))
02813                 return result;
02814         
02815         /* Get domain policy handle */
02816         
02817         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02818                                       MAXIMUM_ALLOWED_ACCESS,
02819                                       domain_sid, &domain_pol);
02820 
02821         if (!NT_STATUS_IS_OK(result))
02822                 return result;
02823 
02824         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
02825                                        1, argv, &num_rids, &rids, &rid_types);
02826 
02827         if (!NT_STATUS_IS_OK(result)) {
02828 
02829                 /* Ok, did not find it in the global sam, try with builtin */
02830 
02831                 DOM_SID sid_Builtin;
02832 
02833                 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
02834 
02835                 string_to_sid(&sid_Builtin, "S-1-5-32");                
02836 
02837                 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02838                                               MAXIMUM_ALLOWED_ACCESS,
02839                                               &sid_Builtin, &domain_pol);
02840 
02841                 if (!NT_STATUS_IS_OK(result)) {
02842                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
02843                         return result;
02844                 }
02845 
02846                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
02847                                                1, argv, &num_rids,
02848                                                &rids, &rid_types);
02849 
02850                 if (!NT_STATUS_IS_OK(result)) {
02851                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
02852                         return result;
02853                 }
02854         }
02855 
02856         if (num_rids != 1) {
02857                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
02858                 return result;
02859         }
02860 
02861         if (rid_types[0] == SID_NAME_DOM_GRP) {
02862                 return rpc_list_group_members(pipe_hnd, mem_ctx, domain_name,
02863                                               domain_sid, &domain_pol,
02864                                               rids[0]);
02865         }
02866 
02867         if (rid_types[0] == SID_NAME_ALIAS) {
02868                 return rpc_list_alias_members(pipe_hnd, mem_ctx, &domain_pol,
02869                                               rids[0]);
02870         }
02871 
02872         return NT_STATUS_NO_SUCH_GROUP;
02873 }
02874 
02875 static int rpc_group_members(int argc, const char **argv)
02876 {
02877         if (argc != 1) {
02878                 return rpc_group_usage(argc, argv);
02879         }
02880 
02881         return run_rpc_command(NULL, PI_SAMR, 0,
02882                                rpc_group_members_internals,
02883                                argc, argv);
02884 }
02885 
02886 static NTSTATUS rpc_group_rename_internals(const DOM_SID *domain_sid,
02887                                         const char *domain_name, 
02888                                         struct cli_state *cli,
02889                                         struct rpc_pipe_client *pipe_hnd,
02890                                         TALLOC_CTX *mem_ctx,
02891                                         int argc,
02892                                         const char **argv)
02893 {
02894         NTSTATUS result;
02895         POLICY_HND connect_pol, domain_pol, group_pol;
02896         uint32 num_rids, *rids, *rid_types;
02897         GROUP_INFO_CTR ctr;
02898 
02899         if (argc != 2) {
02900                 d_printf("Usage: 'net rpc group rename group newname'\n");
02901                 return NT_STATUS_UNSUCCESSFUL;
02902         }
02903 
02904         /* Get sam policy handle */
02905         
02906         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
02907                                   &connect_pol);
02908 
02909         if (!NT_STATUS_IS_OK(result))
02910                 return result;
02911         
02912         /* Get domain policy handle */
02913         
02914         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
02915                                       MAXIMUM_ALLOWED_ACCESS,
02916                                       domain_sid, &domain_pol);
02917 
02918         if (!NT_STATUS_IS_OK(result))
02919                 return result;
02920 
02921         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
02922                                        1, argv, &num_rids, &rids, &rid_types);
02923 
02924         if (num_rids != 1) {
02925                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
02926                 return result;
02927         }
02928 
02929         if (rid_types[0] != SID_NAME_DOM_GRP) {
02930                 d_fprintf(stderr, "Can only rename domain groups\n");
02931                 return NT_STATUS_UNSUCCESSFUL;
02932         }
02933 
02934         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
02935                                      MAXIMUM_ALLOWED_ACCESS,
02936                                      rids[0], &group_pol);
02937 
02938         if (!NT_STATUS_IS_OK(result))
02939                 return result;
02940 
02941         ZERO_STRUCT(ctr);
02942 
02943         ctr.switch_value1 = 2;
02944         init_samr_group_info2(&ctr.group.info2, argv[1]);
02945 
02946         result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &ctr);
02947 
02948         if (!NT_STATUS_IS_OK(result))
02949                 return result;
02950 
02951         return NT_STATUS_NO_SUCH_GROUP;
02952 }
02953 
02954 static int rpc_group_rename(int argc, const char **argv)
02955 {
02956         if (argc != 2) {
02957                 return rpc_group_usage(argc, argv);
02958         }
02959 
02960         return run_rpc_command(NULL, PI_SAMR, 0,
02961                                rpc_group_rename_internals,
02962                                argc, argv);
02963 }
02964 
02965 /** 
02966  * 'net rpc group' entrypoint.
02967  * @param argc  Standard main() style argc
02968  * @param argc  Standard main() style argv.  Initial components are already
02969  *              stripped
02970  **/
02971 
02972 int net_rpc_group(int argc, const char **argv) 
02973 {
02974         struct functable func[] = {
02975                 {"add", rpc_group_add},
02976                 {"delete", rpc_group_delete},
02977                 {"addmem", rpc_group_addmem},
02978                 {"delmem", rpc_group_delmem},
02979                 {"list", rpc_group_list},
02980                 {"members", rpc_group_members},
02981                 {"rename", rpc_group_rename},
02982                 {NULL, NULL}
02983         };
02984         
02985         if (argc == 0) {
02986                 return run_rpc_command(NULL, PI_SAMR, 0, 
02987                                        rpc_group_list_internals,
02988                                        argc, argv);
02989         }
02990 
02991         return net_run_function(argc, argv, func, rpc_group_usage);
02992 }
02993 
02994 /****************************************************************************/
02995 
02996 static int rpc_share_usage(int argc, const char **argv)
02997 {
02998         return net_help_share(argc, argv);
02999 }
03000 
03001 /** 
03002  * Add a share on a remote RPC server
03003  *
03004  * All parameters are provided by the run_rpc_command function, except for
03005  * argc, argv which are passes through. 
03006  *
03007  * @param domain_sid The domain sid acquired from the remote server
03008  * @param cli A cli_state connected to the server.
03009  * @param mem_ctx Talloc context, destoyed on completion of the function.
03010  * @param argc  Standard main() style argc
03011  * @param argv  Standard main() style argv.  Initial components are already
03012  *              stripped
03013  *
03014  * @return Normal NTSTATUS return.
03015  **/
03016 static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid,
03017                                         const char *domain_name, 
03018                                         struct cli_state *cli,
03019                                         struct rpc_pipe_client *pipe_hnd,
03020                                         TALLOC_CTX *mem_ctx,int argc,
03021                                         const char **argv)
03022 {
03023         WERROR result;
03024         char *sharename;
03025         char *path;
03026         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
03027         uint32 num_users=0, perms=0;
03028         char *password=NULL; /* don't allow a share password */
03029         uint32 level = 2;
03030 
03031         if ((sharename = talloc_strdup(mem_ctx, argv[0])) == NULL) {
03032                 return NT_STATUS_NO_MEMORY;
03033         }
03034 
03035         path = strchr(sharename, '=');
03036         if (!path)
03037                 return NT_STATUS_UNSUCCESSFUL;
03038         *path++ = '\0';
03039 
03040         result = rpccli_srvsvc_net_share_add(pipe_hnd, mem_ctx, sharename, type,
03041                                           opt_comment, perms, opt_maxusers,
03042                                           num_users, path, password, 
03043                                           level, NULL);
03044         return werror_to_ntstatus(result);
03045 }
03046 
03047 static int rpc_share_add(int argc, const char **argv)
03048 {
03049         if ((argc < 1) || !strchr(argv[0], '=')) {
03050                 DEBUG(1,("Sharename or path not specified on add\n"));
03051                 return rpc_share_usage(argc, argv);
03052         }
03053         return run_rpc_command(NULL, PI_SRVSVC, 0, 
03054                                rpc_share_add_internals,
03055                                argc, argv);
03056 }
03057 
03058 /** 
03059  * Delete a share on a remote RPC server
03060  *
03061  * All parameters are provided by the run_rpc_command function, except for
03062  * argc, argv which are passes through. 
03063  *
03064  * @param domain_sid The domain sid acquired from the remote server
03065  * @param cli A cli_state connected to the server.
03066  * @param mem_ctx Talloc context, destoyed on completion of the function.
03067  * @param argc  Standard main() style argc
03068  * @param argv  Standard main() style argv.  Initial components are already
03069  *              stripped
03070  *
03071  * @return Normal NTSTATUS return.
03072  **/
03073 static NTSTATUS rpc_share_del_internals(const DOM_SID *domain_sid,
03074                                         const char *domain_name, 
03075                                         struct cli_state *cli,
03076                                         struct rpc_pipe_client *pipe_hnd,
03077                                         TALLOC_CTX *mem_ctx,
03078                                         int argc,
03079                                         const char **argv)
03080 {
03081         WERROR result;
03082 
03083         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
03084         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
03085 }
03086 
03087 /** 
03088  * Delete a share on a remote RPC server
03089  *
03090  * @param domain_sid The domain sid acquired from the remote server
03091  * @param argc  Standard main() style argc
03092  * @param argv  Standard main() style argv.  Initial components are already
03093  *              stripped
03094  *
03095  * @return A shell status integer (0 for success)
03096  **/
03097 static int rpc_share_delete(int argc, const char **argv)
03098 {
03099         if (argc < 1) {
03100                 DEBUG(1,("Sharename not specified on delete\n"));
03101                 return rpc_share_usage(argc, argv);
03102         }
03103         return run_rpc_command(NULL, PI_SRVSVC, 0, 
03104                                rpc_share_del_internals,
03105                                argc, argv);
03106 }
03107 
03108 /**
03109  * Formatted print of share info
03110  *
03111  * @param info1  pointer to SRV_SHARE_INFO_1 to format
03112  **/
03113  
03114 static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
03115 {
03116         fstring netname = "", remark = "";
03117 
03118         rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
03119         rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
03120 
03121         if (opt_long_list_entries) {
03122                 d_printf("%-12s %-8.8s %-50s\n",
03123                          netname, share_type[info1->info_1.type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)], remark);
03124         } else {
03125                 d_printf("%s\n", netname);
03126         }
03127 
03128 }
03129 
03130 static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd,
03131                                 TALLOC_CTX *mem_ctx, 
03132                                 uint32 level,
03133                                 int argc,
03134                                 const char **argv, 
03135                                 SRV_SHARE_INFO_CTR *ctr)
03136 {
03137         WERROR result;
03138         SRV_SHARE_INFO info;
03139 
03140         /* no specific share requested, enumerate all */
03141         if (argc == 0) {
03142 
03143                 ENUM_HND hnd;
03144                 uint32 preferred_len = 0xffffffff;
03145 
03146                 init_enum_hnd(&hnd, 0);
03147 
03148                 return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr, 
03149                                                  preferred_len, &hnd);
03150         }
03151 
03152         /* request just one share */
03153         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info);
03154 
03155         if (!W_ERROR_IS_OK(result))
03156                 goto done;
03157 
03158         /* construct ctr */
03159         ZERO_STRUCTP(ctr);
03160 
03161         ctr->info_level = ctr->switch_value = level;
03162         ctr->ptr_share_info = ctr->ptr_entries = 1;
03163         ctr->num_entries = ctr->num_entries2 = 1;
03164 
03165         switch (level) {
03166         case 1:
03167         {
03168                 char *s;
03169                 SRV_SHARE_INFO_1 *info1;
03170                 
03171                 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
03172                 if (ctr->share.info1 == NULL) {
03173                         result = WERR_NOMEM;
03174                         goto done;
03175                 }
03176                 info1 = ctr->share.info1;
03177                                 
03178                 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
03179 
03180                 /* Copy pointer crap */
03181 
03182                 memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
03183 
03184                 /* Duplicate strings */
03185 
03186                 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_netname);
03187                 if (s)
03188                         init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
03189 
03190                 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_remark);
03191                 if (s)
03192                         init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
03193         }
03194         case 2:
03195         {
03196                 char *s;
03197                 SRV_SHARE_INFO_2 *info2;
03198                 
03199                 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
03200                 if (ctr->share.info2 == NULL) {
03201                         result = WERR_NOMEM;
03202                         goto done;
03203                 }
03204                 info2 = ctr->share.info2;
03205                                 
03206                 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
03207 
03208                 /* Copy pointer crap */
03209 
03210                 memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
03211 
03212                 /* Duplicate strings */
03213 
03214                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_netname);
03215                 if (s)
03216                         init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
03217 
03218                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_remark);
03219                 if (s)
03220                         init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
03221 
03222                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_path);
03223                 if (s)
03224                         init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
03225 
03226                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
03227                 if (s)
03228                         init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
03229         }
03230         case 502:
03231         {
03232                 char *s;
03233                 SRV_SHARE_INFO_502 *info502;
03234 
03235                 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
03236                 if (ctr->share.info502 == NULL) {
03237                         result = WERR_NOMEM;
03238                         goto done;
03239                 }
03240                 info502 = ctr->share.info502;
03241 
03242                 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
03243 
03244                 /* Copy pointer crap */
03245 
03246                 memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
03247 
03248                 /* Duplicate strings */
03249 
03250                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_netname);
03251                 if (s)
03252                         init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
03253 
03254                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_remark);
03255                 if (s)
03256                         init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
03257 
03258                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_path);
03259                 if (s)
03260                         init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
03261 
03262                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
03263                 if (s)
03264                         init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
03265 
03266                 info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
03267                                 
03268         }
03269 
03270         } /* switch */
03271 
03272 done:
03273         return result;
03274 }
03275 
03276 /** 
03277  * List shares on a remote RPC server
03278  *
03279  * All parameters are provided by the run_rpc_command function, except for
03280  * argc, argv which are passes through. 
03281  *
03282  * @param domain_sid The domain sid acquired from the remote server
03283  * @param cli A cli_state connected to the server.
03284  * @param mem_ctx Talloc context, destoyed on completion of the function.
03285  * @param argc  Standard main() style argc
03286  * @param argv  Standard main() style argv.  Initial components are already
03287  *              stripped
03288  *
03289  * @return Normal NTSTATUS return.
03290  **/
03291 
03292 static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid,
03293                                         const char *domain_name, 
03294                                         struct cli_state *cli,
03295                                         struct rpc_pipe_client *pipe_hnd,
03296                                         TALLOC_CTX *mem_ctx,
03297                                         int argc,
03298                                         const char **argv)
03299 {
03300         SRV_SHARE_INFO_CTR ctr;
03301         WERROR result;
03302         uint32 i, level = 1;
03303 
03304         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr);
03305         if (!W_ERROR_IS_OK(result))
03306                 goto done;
03307 
03308         /* Display results */
03309 
03310         if (opt_long_list_entries) {
03311                 d_printf(
03312         "\nEnumerating shared resources (exports) on remote server:\n\n"\
03313         "\nShare name   Type     Description\n"\
03314         "----------   ----     -----------\n");
03315         }
03316         for (i = 0; i < ctr.num_entries; i++)
03317                 display_share_info_1(&ctr.share.info1[i]);
03318  done:
03319         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
03320 }
03321 
03322 /*** 
03323  * 'net rpc share list' entrypoint.
03324  * @param argc  Standard main() style argc
03325  * @param argv  Standard main() style argv.  Initial components are already
03326  *              stripped
03327  **/
03328 static int rpc_share_list(int argc, const char **argv)
03329 {
03330         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
03331 }
03332 
03333 static BOOL check_share_availability(struct cli_state *cli, const char *netname)
03334 {
03335         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
03336                 d_printf("skipping   [%s]: not a file share.\n", netname);
03337                 return False;
03338         }
03339 
03340         if (!cli_tdis(cli)) 
03341                 return False;
03342 
03343         return True;
03344 }
03345 
03346 static BOOL check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
03347 {
03348         /* only support disk shares */
03349         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
03350                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
03351                 return False;
03352         }
03353 
03354         /* skip builtin shares */
03355         /* FIXME: should print$ be added too ? */
03356         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") || 
03357             strequal(netname,"global")) 
03358                 return False;
03359 
03360         if (opt_exclude && in_list(netname, opt_exclude, False)) {
03361                 printf("excluding  [%s]\n", netname);
03362                 return False;
03363         }
03364 
03365         return check_share_availability(cli, netname);
03366 }
03367 
03368 /** 
03369  * Migrate shares from a remote RPC server to the local RPC srever
03370  *
03371  * All parameters are provided by the run_rpc_command function, except for
03372  * argc, argv which are passes through. 
03373  *
03374  * @param domain_sid The domain sid acquired from the remote server
03375  * @param cli A cli_state connected to the server.
03376  * @param mem_ctx Talloc context, destoyed on completion of the function.
03377  * @param argc  Standard main() style argc
03378  * @param argv  Standard main() style argv.  Initial components are already
03379  *              stripped
03380  *
03381  * @return Normal NTSTATUS return.
03382  **/
03383 
03384 static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid,
03385                                                 const char *domain_name, 
03386                                                 struct cli_state *cli,
03387                                                 struct rpc_pipe_client *pipe_hnd,
03388                                                 TALLOC_CTX *mem_ctx, 
03389                                                 int argc,
03390                                                 const char **argv)
03391 {
03392         WERROR result;
03393         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
03394         SRV_SHARE_INFO_CTR ctr_src;
03395         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
03396         char *password = NULL; /* don't allow a share password */
03397         uint32 i;
03398         struct rpc_pipe_client *srvsvc_pipe = NULL;
03399         struct cli_state *cli_dst = NULL;
03400         uint32 level = 502; /* includes secdesc */
03401 
03402         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
03403         if (!W_ERROR_IS_OK(result))
03404                 goto done;
03405 
03406         /* connect destination PI_SRVSVC */
03407         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
03408         if (!NT_STATUS_IS_OK(nt_status))
03409                 return nt_status;
03410 
03411 
03412         for (i = 0; i < ctr_src.num_entries; i++) {
03413 
03414                 fstring netname = "", remark = "", path = "";
03415                 /* reset error-code */
03416                 nt_status = NT_STATUS_UNSUCCESSFUL;
03417 
03418                 rpcstr_pull_unistr2_fstring(
03419                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
03420                 rpcstr_pull_unistr2_fstring(
03421                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
03422                 rpcstr_pull_unistr2_fstring(
03423                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
03424 
03425                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
03426                         continue;
03427 
03428                 /* finally add the share on the dst server */ 
03429 
03430                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
03431                         netname, path, remark);
03432 
03433                 result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark,
03434                                                   ctr_src.share.info502[i].info_502.perms,
03435                                                   ctr_src.share.info502[i].info_502.max_uses,
03436                                                   ctr_src.share.info502[i].info_502.num_uses,
03437                                                   path, password, level, 
03438                                                   NULL);
03439         
03440                 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
03441                         printf("           [%s] does already exist\n", netname);
03442                         continue;
03443                 }
03444 
03445                 if (!W_ERROR_IS_OK(result)) {
03446                         printf("cannot add share: %s\n", dos_errstr(result));
03447                         goto done;
03448                 }
03449 
03450         }
03451 
03452         nt_status = NT_STATUS_OK;
03453 
03454 done:
03455         if (cli_dst) {
03456                 cli_shutdown(cli_dst);
03457         }
03458 
03459         return nt_status;
03460 
03461 }
03462 
03463 /** 
03464  * Migrate shares from a rpc-server to another
03465  *
03466  * @param argc  Standard main() style argc
03467  * @param argv  Standard main() style argv.  Initial components are already
03468  *              stripped
03469  *
03470  * @return A shell status integer (0 for success)
03471  **/
03472 static int rpc_share_migrate_shares(int argc, const char **argv)
03473 {
03474 
03475         if (!opt_host) {
03476                 printf("no server to migrate\n");
03477                 return -1;
03478         }
03479 
03480         return run_rpc_command(NULL, PI_SRVSVC, 0, 
03481                                rpc_share_migrate_shares_internals,
03482                                argc, argv);
03483 }
03484 
03485 /**
03486  * Copy a file/dir 
03487  *
03488  * @param f     file_info
03489  * @param mask  current search mask
03490  * @param state arg-pointer
03491  *
03492  **/
03493 static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
03494 {
03495         static NTSTATUS nt_status;
03496         static struct copy_clistate *local_state;
03497         static fstring filename, new_mask;
03498         fstring dir;
03499         char *old_dir;
03500 
03501         local_state = (struct copy_clistate *)state;
03502         nt_status = NT_STATUS_UNSUCCESSFUL;
03503 
03504         if (strequal(f->name, ".") || strequal(f->name, ".."))
03505                 return;
03506 
03507         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
03508 
03509         /* DIRECTORY */
03510         if (f->mode & aDIR) {
03511 
03512                 DEBUG(3,("got dir: %s\n", f->name));
03513 
03514                 fstrcpy(dir, local_state->cwd);
03515                 fstrcat(dir, "\\");
03516                 fstrcat(dir, f->name);
03517 
03518                 switch (net_mode_share)
03519                 {
03520                 case NET_MODE_SHARE_MIGRATE:
03521                         /* create that directory */
03522                         nt_status = net_copy_file(local_state->mem_ctx,
03523                                                   local_state->cli_share_src,
03524                                                   local_state->cli_share_dst,
03525                                                   dir, dir,
03526                                                   opt_acls? True : False,
03527                                                   opt_attrs? True : False,
03528                                                   opt_timestamps? True : False,
03529                                                   False);
03530                         break;
03531                 default:
03532                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
03533                         return;
03534                 }
03535 
03536                 if (!NT_STATUS_IS_OK(nt_status)) 
03537                         printf("could not handle dir %s: %s\n", 
03538                                 dir, nt_errstr(nt_status));
03539 
03540                 /* search below that directory */
03541                 fstrcpy(new_mask, dir);
03542                 fstrcat(new_mask, "\\*");
03543 
03544                 old_dir = local_state->cwd;
03545                 local_state->cwd = dir;
03546                 if (!sync_files(local_state, new_mask))
03547                         printf("could not handle files\n");
03548                 local_state->cwd = old_dir;
03549 
03550                 return;
03551         }
03552 
03553 
03554         /* FILE */
03555         fstrcpy(filename, local_state->cwd);
03556         fstrcat(filename, "\\");
03557         fstrcat(filename, f->name);
03558 
03559         DEBUG(3,("got file: %s\n", filename));
03560 
03561         switch (net_mode_share)
03562         {
03563         case NET_MODE_SHARE_MIGRATE:
03564                 nt_status = net_copy_file(local_state->mem_ctx, 
03565                                           local_state->cli_share_src, 
03566                                           local_state->cli_share_dst, 
03567                                           filename, filename, 
03568                                           opt_acls? True : False, 
03569                                           opt_attrs? True : False,
03570                                           opt_timestamps? True: False,
03571                                           True);
03572                 break;
03573         default:
03574                 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
03575                 return;
03576         }
03577 
03578         if (!NT_STATUS_IS_OK(nt_status)) 
03579                 printf("could not handle file %s: %s\n", 
03580                         filename, nt_errstr(nt_status));
03581 
03582 }
03583 
03584 /**
03585  * sync files, can be called recursivly to list files 
03586  * and then call copy_fn for each file 
03587  *
03588  * @param cp_clistate   pointer to the copy_clistate we work with
03589  * @param mask          the current search mask
03590  *
03591  * @return              Boolean result
03592  **/
03593 BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask)
03594 {
03595         struct cli_state *targetcli;
03596         pstring targetpath;
03597 
03598         DEBUG(3,("calling cli_list with mask: %s\n", mask));
03599 
03600         if ( !cli_resolve_path( "", cp_clistate->cli_share_src, mask, &targetcli, targetpath ) ) {
03601                 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", 
03602                         mask, cli_errstr(cp_clistate->cli_share_src));
03603                 return False;
03604         }
03605 
03606         if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
03607                 d_fprintf(stderr, "listing %s failed with error: %s\n", 
03608                         mask, cli_errstr(targetcli));
03609                 return False;
03610         }
03611 
03612         return True;
03613 }
03614 
03615 
03616 /**
03617  * Set the top level directory permissions before we do any further copies.
03618  * Should set up ACL inheritance.
03619  **/
03620 
03621 BOOL copy_top_level_perms(struct copy_clistate *cp_clistate, 
03622                                 const char *sharename)
03623 {
03624         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
03625 
03626         switch (net_mode_share) {
03627         case NET_MODE_SHARE_MIGRATE:
03628                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
03629                 nt_status = net_copy_fileattr(cp_clistate->mem_ctx,
03630                                                 cp_clistate->cli_share_src, 
03631                                                 cp_clistate->cli_share_dst,
03632                                                 "\\", "\\",
03633                                                 opt_acls? True : False, 
03634                                                 opt_attrs? True : False,
03635                                                 opt_timestamps? True: False,
03636                                                 False);
03637                 break;
03638         default:
03639                 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
03640                 break;
03641         }
03642 
03643         if (!NT_STATUS_IS_OK(nt_status))  {
03644                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
03645                         sharename, nt_errstr(nt_status));
03646                 return False;
03647         }
03648 
03649         return True;
03650 }
03651 
03652 /** 
03653  * Sync all files inside a remote share to another share (over smb)
03654  *
03655  * All parameters are provided by the run_rpc_command function, except for
03656  * argc, argv which are passes through. 
03657  *
03658  * @param domain_sid The domain sid acquired from the remote server
03659  * @param cli A cli_state connected to the server.
03660  * @param mem_ctx Talloc context, destoyed on completion of the function.
03661  * @param argc  Standard main() style argc
03662  * @param argv  Standard main() style argv.  Initial components are already
03663  *              stripped
03664  *
03665  * @return Normal NTSTATUS return.
03666  **/
03667 
03668 static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid,
03669                                                 const char *domain_name, 
03670                                                 struct cli_state *cli,
03671                                                 struct rpc_pipe_client *pipe_hnd,
03672                                                 TALLOC_CTX *mem_ctx,
03673                                                 int argc,
03674                                                 const char **argv)
03675 {
03676         WERROR result;
03677         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
03678         SRV_SHARE_INFO_CTR ctr_src;
03679         uint32 i;
03680         uint32 level = 502;
03681         struct copy_clistate cp_clistate;
03682         BOOL got_src_share = False;
03683         BOOL got_dst_share = False;
03684         pstring mask = "\\*";
03685         char *dst = NULL;
03686 
03687         dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
03688 
03689         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
03690 
03691         if (!W_ERROR_IS_OK(result))
03692                 goto done;
03693 
03694         for (i = 0; i < ctr_src.num_entries; i++) {
03695 
03696                 fstring netname = "";
03697 
03698                 rpcstr_pull_unistr2_fstring(
03699                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
03700 
03701                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
03702                         continue;
03703 
03704                 /* one might not want to mirror whole discs :) */
03705                 if (strequal(netname, "print$") || netname[1] == '$') {
03706                         d_printf("skipping   [%s]: builtin/hidden share\n", netname);
03707                         continue;
03708                 }
03709 
03710                 switch (net_mode_share)
03711                 {
03712                 case NET_MODE_SHARE_MIGRATE:
03713                         printf("syncing");
03714                         break;
03715                 default:
03716                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
03717                         break;
03718                 }
03719                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
03720                         netname, 
03721                         opt_acls ? "including" : "without", 
03722                         opt_attrs ? "including" : "without",
03723                         opt_timestamps ? "(preserving timestamps)" : "");
03724 
03725                 cp_clistate.mem_ctx = mem_ctx;
03726                 cp_clistate.cli_share_src = NULL;
03727                 cp_clistate.cli_share_dst = NULL;
03728                 cp_clistate.cwd = NULL;
03729                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
03730 
03731                 /* open share source */
03732                 nt_status = connect_to_service(&cp_clistate.cli_share_src,
03733                                                &cli->dest_ip, cli->desthost,
03734                                                netname, "A:");
03735                 if (!NT_STATUS_IS_OK(nt_status))
03736                         goto done;
03737 
03738                 got_src_share = True;
03739 
03740                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
03741                         /* open share destination */
03742                         nt_status = connect_to_service(&cp_clistate.cli_share_dst,
03743                                                        NULL, dst, netname, "A:");
03744                         if (!NT_STATUS_IS_OK(nt_status))
03745                                 goto done;
03746 
03747                         got_dst_share = True;
03748                 }
03749 
03750                 if (!copy_top_level_perms(&cp_clistate, netname)) {
03751                         d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", netname);
03752                         nt_status = NT_STATUS_UNSUCCESSFUL;
03753                         goto done;
03754                 }
03755 
03756                 if (!sync_files(&cp_clistate, mask)) {
03757                         d_fprintf(stderr, "could not handle files for share: %s\n", netname);
03758                         nt_status = NT_STATUS_UNSUCCESSFUL;
03759                         goto done;
03760                 }
03761         }
03762 
03763         nt_status = NT_STATUS_OK;
03764 
03765 done:
03766 
03767         if (got_src_share)
03768                 cli_shutdown(cp_clistate.cli_share_src);
03769 
03770         if (got_dst_share)
03771                 cli_shutdown(cp_clistate.cli_share_dst);
03772 
03773         return nt_status;
03774 
03775 }
03776 
03777 static int rpc_share_migrate_files(int argc, const char **argv)
03778 {
03779 
03780         if (!opt_host) {
03781                 printf("no server to migrate\n");
03782                 return -1;
03783         }
03784 
03785         return run_rpc_command(NULL, PI_SRVSVC, 0, 
03786                                rpc_share_migrate_files_internals,
03787                                argc, argv);
03788 }
03789 
03790 /** 
03791  * Migrate share-ACLs from a remote RPC server to the local RPC srever
03792  *
03793  * All parameters are provided by the run_rpc_command function, except for
03794  * argc, argv which are passes through. 
03795  *
03796  * @param domain_sid The domain sid acquired from the remote server
03797  * @param cli A cli_state connected to the server.
03798  * @param mem_ctx Talloc context, destoyed on completion of the function.
03799  * @param argc  Standard main() style argc
03800  * @param argv  Standard main() style argv.  Initial components are already
03801  *              stripped
03802  *
03803  * @return Normal NTSTATUS return.
03804  **/
03805 
03806 static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid,
03807                                                 const char *domain_name, 
03808                                                 struct cli_state *cli,
03809                                                 struct rpc_pipe_client *pipe_hnd,
03810                                                 TALLOC_CTX *mem_ctx, 
03811                                                 int argc,
03812                                                 const char **argv)
03813 {
03814         WERROR result;
03815         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
03816         SRV_SHARE_INFO_CTR ctr_src;
03817         SRV_SHARE_INFO info;
03818         uint32 i;
03819         struct rpc_pipe_client *srvsvc_pipe = NULL;
03820         struct cli_state *cli_dst = NULL;
03821         uint32 level = 502; /* includes secdesc */
03822 
03823         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
03824 
03825         if (!W_ERROR_IS_OK(result))
03826                 goto done;
03827 
03828         /* connect destination PI_SRVSVC */
03829         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
03830         if (!NT_STATUS_IS_OK(nt_status))
03831                 return nt_status;
03832 
03833 
03834         for (i = 0; i < ctr_src.num_entries; i++) {
03835 
03836                 fstring netname = "", remark = "", path = "";
03837                 /* reset error-code */
03838                 nt_status = NT_STATUS_UNSUCCESSFUL;
03839 
03840                 rpcstr_pull_unistr2_fstring(
03841                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
03842                 rpcstr_pull_unistr2_fstring(
03843                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
03844                 rpcstr_pull_unistr2_fstring(
03845                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
03846 
03847                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
03848                         continue;
03849 
03850                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
03851                         netname, path, remark);
03852 
03853                 if (opt_verbose)
03854                         display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
03855 
03856                 /* init info */
03857                 ZERO_STRUCT(info);
03858 
03859                 info.switch_value = level;
03860                 info.ptr_share_ctr = 1;
03861 
03862                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
03863                 info.share.info502 = ctr_src.share.info502[i];
03864 
03865                 /* finally modify the share on the dst server */
03866                 result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info);
03867         
03868                 if (!W_ERROR_IS_OK(result)) {
03869                         printf("cannot set share-acl: %s\n", dos_errstr(result));
03870                         goto done;
03871                 }
03872 
03873         }
03874 
03875         nt_status = NT_STATUS_OK;
03876 
03877 done:
03878         if (cli_dst) {
03879                 cli_shutdown(cli_dst);
03880         }
03881 
03882         return nt_status;
03883 
03884 }
03885 
03886 /** 
03887  * Migrate share-acls from a rpc-server to another
03888  *
03889  * @param argc  Standard main() style argc
03890  * @param argv  Standard main() style argv.  Initial components are already
03891  *              stripped
03892  *
03893  * @return A shell status integer (0 for success)
03894  **/
03895 static int rpc_share_migrate_security(int argc, const char **argv)
03896 {
03897 
03898         if (!opt_host) {
03899                 printf("no server to migrate\n");
03900                 return -1;
03901         }
03902 
03903         return run_rpc_command(NULL, PI_SRVSVC, 0, 
03904                                rpc_share_migrate_security_internals,
03905                                argc, argv);
03906 }
03907 
03908 /** 
03909  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
03910  * from one server to another
03911  *
03912  * @param argc  Standard main() style argc
03913  * @param argv  Standard main() style argv.  Initial components are already
03914  *              stripped
03915  *
03916  * @return A shell status integer (0 for success)
03917  *
03918  **/
03919 static int rpc_share_migrate_all(int argc, const char **argv)
03920 {
03921         int ret;
03922 
03923         if (!opt_host) {
03924                 printf("no server to migrate\n");
03925                 return -1;
03926         }
03927 
03928         /* order is important. we don't want to be locked out by the share-acl
03929          * before copying files - gd */
03930         
03931         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
03932         if (ret)
03933                 return ret;
03934 
03935         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
03936         if (ret)
03937                 return ret;
03938         
03939         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
03940 }
03941 
03942 
03943 /** 
03944  * 'net rpc share migrate' entrypoint.
03945  * @param argc  Standard main() style argc
03946  * @param argv  Standard main() style argv.  Initial components are already
03947  *              stripped
03948  **/
03949 static int rpc_share_migrate(int argc, const char **argv)
03950 {
03951 
03952         struct functable func[] = {
03953                 {"all",         rpc_share_migrate_all},
03954                 {"files",       rpc_share_migrate_files},
03955                 {"help",        rpc_share_usage},
03956                 {"security",    rpc_share_migrate_security},
03957                 {"shares",      rpc_share_migrate_shares},
03958                 {NULL, NULL}
03959         };
03960 
03961         net_mode_share = NET_MODE_SHARE_MIGRATE;
03962 
03963         return net_run_function(argc, argv, func, rpc_share_usage);
03964 }
03965 
03966 struct full_alias {
03967         DOM_SID sid;
03968         uint32 num_members;
03969         DOM_SID *members;
03970 };
03971 
03972 static int num_server_aliases;
03973 static struct full_alias *server_aliases;
03974 
03975 /*
03976  * Add an alias to the static list.
03977  */
03978 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
03979 {
03980         if (server_aliases == NULL)
03981                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
03982 
03983         server_aliases[num_server_aliases] = *alias;
03984         num_server_aliases += 1;
03985 }
03986 
03987 /*
03988  * For a specific domain on the server, fetch all the aliases
03989  * and their members. Add all of them to the server_aliases.
03990  */
03991 
03992 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
03993                                         TALLOC_CTX *mem_ctx,
03994                                         POLICY_HND *connect_pol,
03995                                         const DOM_SID *domain_sid)
03996 {
03997         uint32 start_idx, max_entries, num_entries, i;
03998         struct acct_info *groups;
03999         NTSTATUS result;
04000         POLICY_HND domain_pol;
04001 
04002         /* Get domain policy handle */
04003         
04004         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, connect_pol,
04005                                       MAXIMUM_ALLOWED_ACCESS,
04006                                       domain_sid, &domain_pol);
04007         if (!NT_STATUS_IS_OK(result))
04008                 return result;
04009 
04010         start_idx = 0;
04011         max_entries = 250;
04012 
04013         do {
04014                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
04015                                                   &start_idx, max_entries,
04016                                                   &groups, &num_entries);
04017 
04018                 for (i = 0; i < num_entries; i++) {
04019 
04020                         POLICY_HND alias_pol;
04021                         struct full_alias alias;
04022                         DOM_SID *members;
04023                         int j;
04024 
04025                         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
04026                                                      MAXIMUM_ALLOWED_ACCESS,
04027                                                      groups[i].rid,
04028                                                      &alias_pol);
04029                         if (!NT_STATUS_IS_OK(result))
04030                                 goto done;
04031 
04032                         result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx,
04033                                                          &alias_pol,
04034                                                          &alias.num_members,
04035                                                          &members);
04036                         if (!NT_STATUS_IS_OK(result))
04037                                 goto done;
04038 
04039                         result = rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol);
04040                         if (!NT_STATUS_IS_OK(result))
04041                                 goto done;
04042 
04043                         alias.members = NULL;
04044 
04045                         if (alias.num_members > 0) {
04046                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
04047 
04048                                 for (j = 0; j < alias.num_members; j++)
04049                                         sid_copy(&alias.members[j],
04050                                                  &members[j]);
04051                         }
04052 
04053                         sid_copy(&alias.sid, domain_sid);
04054                         sid_append_rid(&alias.sid, groups[i].rid);
04055 
04056                         push_alias(mem_ctx, &alias);
04057                 }
04058         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
04059 
04060         result = NT_STATUS_OK;
04061 
04062  done:
04063         rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
04064 
04065         return result;
04066 }
04067 
04068 /*
04069  * Dump server_aliases as names for debugging purposes.
04070  */
04071 
04072 static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid,
04073                                 const char *domain_name,
04074                                 struct cli_state *cli,
04075                                 struct rpc_pipe_client *pipe_hnd,
04076                                 TALLOC_CTX *mem_ctx, 
04077                                 int argc,
04078                                 const char **argv)
04079 {
04080         int i;
04081         NTSTATUS result;
04082         POLICY_HND lsa_pol;
04083 
04084         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
04085                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
04086                                      &lsa_pol);
04087         if (!NT_STATUS_IS_OK(result))
04088                 return result;
04089 
04090         for (i=0; i<num_server_aliases; i++) {
04091                 char **names;
04092                 char **domains;
04093                 uint32 *types;
04094                 int j;
04095 
04096                 struct full_alias *alias = &server_aliases[i];
04097 
04098                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
04099                                              &alias->sid,
04100                                              &domains, &names, &types);
04101                 if (!NT_STATUS_IS_OK(result))
04102                         continue;
04103 
04104                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
04105 
04106                 if (alias->num_members == 0) {
04107                         DEBUG(1, ("\n"));
04108                         continue;
04109                 }
04110 
04111                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
04112                                              alias->num_members,
04113                                              alias->members,
04114                                              &domains, &names, &types);
04115 
04116                 if (!NT_STATUS_IS_OK(result) &&
04117                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
04118                         continue;
04119 
04120                 for (j=0; j<alias->num_members; j++)
04121                         DEBUG(1, ("%s\\%s (%d); ",
04122                                   domains[j] ? domains[j] : "*unknown*", 
04123                                   names[j] ? names[j] : "*unknown*",types[j]));
04124                 DEBUG(1, ("\n"));
04125         }
04126 
04127         rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
04128 
04129         return NT_STATUS_OK;
04130 }
04131 
04132 /*
04133  * Fetch a list of all server aliases and their members into
04134  * server_aliases.
04135  */
04136 
04137 static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid,
04138                                         const char *domain_name,
04139                                         struct cli_state *cli,
04140                                         struct rpc_pipe_client *pipe_hnd,
04141                                         TALLOC_CTX *mem_ctx, 
04142                                         int argc,
04143                                         const char **argv)
04144 {
04145         NTSTATUS result;
04146         POLICY_HND connect_pol;
04147 
04148         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
04149                                   &connect_pol);
04150 
04151         if (!NT_STATUS_IS_OK(result))
04152                 goto done;
04153         
04154         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
04155                                           &global_sid_Builtin);
04156 
04157         if (!NT_STATUS_IS_OK(result))
04158                 goto done;
04159         
04160         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
04161                                           domain_sid);
04162 
04163         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
04164  done:
04165         return result;
04166 }
04167 
04168 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
04169 {
04170         token->num_sids = 4;
04171 
04172         token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4);
04173 
04174         token->user_sids[0] = *user_sid;
04175         sid_copy(&token->user_sids[1], &global_sid_World);
04176         sid_copy(&token->user_sids[2], &global_sid_Network);
04177         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
04178 }
04179 
04180 static void free_user_token(NT_USER_TOKEN *token)
04181 {
04182         SAFE_FREE(token->user_sids);
04183 }
04184 
04185 static BOOL is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
04186 {
04187         int i;
04188 
04189         for (i=0; i<token->num_sids; i++) {
04190                 if (sid_compare(sid, &token->user_sids[i]) == 0)
04191                         return True;
04192         }
04193         return False;
04194 }
04195 
04196 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
04197 {
04198         if (is_sid_in_token(token, sid))
04199                 return;
04200 
04201         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
04202         if (!token->user_sids) {
04203                 return;
04204         }
04205 
04206         sid_copy(&token->user_sids[token->num_sids], sid);
04207 
04208         token->num_sids += 1;
04209 }
04210 
04211 struct user_token {
04212         fstring name;
04213         NT_USER_TOKEN token;
04214 };
04215 
04216 static void dump_user_token(struct user_token *token)
04217 {
04218         int i;
04219 
04220         d_printf("%s\n", token->name);
04221 
04222         for (i=0; i<token->token.num_sids; i++) {
04223                 d_printf(" %s\n", sid_string_static(&token->token.user_sids[i]));
04224         }
04225 }
04226 
04227 static BOOL is_alias_member(DOM_SID *sid, struct full_alias *alias)
04228 {
04229         int i;
04230 
04231         for (i=0; i<alias->num_members; i++) {
04232                 if (sid_compare(sid, &alias->members[i]) == 0)
04233                         return True;
04234         }
04235 
04236         return False;
04237 }
04238 
04239 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
04240 {
04241         int i;
04242 
04243         for (i=0; i<num_server_aliases; i++) {
04244                 if (is_alias_member(&sid, &server_aliases[i]))
04245                         add_sid_to_token(token, &server_aliases[i].sid);
04246         }
04247 }
04248 
04249 /*
04250  * We got a user token with all the SIDs we can know about without asking the
04251  * server directly. These are the user and domain group sids. All of these can
04252  * be members of aliases. So scan the list of aliases for each of the SIDs and
04253  * add them to the token.
04254  */
04255 
04256 static void collect_alias_memberships(NT_USER_TOKEN *token)
04257 {
04258         int num_global_sids = token->num_sids;
04259         int i;
04260 
04261         for (i=0; i<num_global_sids; i++) {
04262                 collect_sid_memberships(token, token->user_sids[i]);
04263         }
04264 }
04265 
04266 static BOOL get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
04267 {
04268         struct winbindd_request request;
04269         struct winbindd_response response;
04270         fstring full_name;
04271         NSS_STATUS result;
04272 
04273         DOM_SID user_sid;
04274 
04275         int i;
04276 
04277         fstr_sprintf(full_name, "%s%c%s",
04278                      domain, *lp_winbind_separator(), user);
04279 
04280         /* First let's find out the user sid */
04281 
04282         ZERO_STRUCT(request);
04283         ZERO_STRUCT(response);
04284 
04285         fstrcpy(request.data.name.dom_name, domain);
04286         fstrcpy(request.data.name.name, user);
04287 
04288         result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
04289 
04290         if (result != NSS_STATUS_SUCCESS) {
04291                 DEBUG(1, ("winbind could not find %s\n", full_name));
04292                 return False;
04293         }
04294 
04295         if (response.data.sid.type != SID_NAME_USER) {
04296                 DEBUG(1, ("%s is not a user\n", full_name));
04297                 return False;
04298         }
04299 
04300         string_to_sid(&user_sid, response.data.sid.sid);
04301 
04302         init_user_token(token, &user_sid);
04303 
04304         /* And now the groups winbind knows about */
04305 
04306         ZERO_STRUCT(response);
04307 
04308         fstrcpy(request.data.username, full_name);
04309 
04310         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
04311 
04312         if (result != NSS_STATUS_SUCCESS) {
04313                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
04314                 return False;
04315         }
04316 
04317         for (i = 0; i < response.data.num_entries; i++) {
04318                 gid_t gid = ((gid_t *)response.extra_data.data)[i];
04319                 DOM_SID sid;
04320 
04321                 struct winbindd_request sidrequest;
04322                 struct winbindd_response sidresponse;
04323 
04324                 ZERO_STRUCT(sidrequest);
04325                 ZERO_STRUCT(sidresponse);
04326 
04327                 sidrequest.data.gid = gid;
04328 
04329                 result = winbindd_request_response(WINBINDD_GID_TO_SID,
04330                                           &sidrequest, &sidresponse);
04331 
04332                 if (result != NSS_STATUS_SUCCESS) {
04333                         DEBUG(1, ("winbind could not find SID of gid %d\n",
04334                                   gid));
04335                         return False;
04336                 }
04337 
04338                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
04339 
04340                 string_to_sid(&sid, sidresponse.data.sid.sid);
04341                 add_sid_to_token(token, &sid);
04342         }
04343 
04344         SAFE_FREE(response.extra_data.data);
04345 
04346         return True;
04347 }
04348         
04349 /**
04350  * Get a list of all user tokens we want to look at
04351  **/
04352 
04353 static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
04354 {
04355         struct winbindd_request request;
04356         struct winbindd_response response;
04357         const char *extra_data;
04358         fstring name;
04359         int i;
04360         struct user_token *result;
04361 
04362         if (lp_winbind_use_default_domain() &&
04363             (opt_target_workgroup == NULL)) {
04364                 d_fprintf(stderr, "winbind use default domain = yes set, "
04365                          "please specify a workgroup\n");
04366                 return False;
04367         }
04368 
04369         /* Send request to winbind daemon */
04370 
04371         ZERO_STRUCT(request);
04372         ZERO_STRUCT(response);
04373         
04374         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
04375             NSS_STATUS_SUCCESS)
04376                 return False;
04377 
04378         /* Look through extra data */
04379 
04380         if (!response.extra_data.data)
04381                 return False;
04382 
04383         extra_data = (const char *)response.extra_data.data;
04384         *num_tokens = 0;
04385 
04386         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
04387                 *num_tokens += 1;
04388         }
04389 
04390         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
04391 
04392         if (result == NULL) {
04393                 DEBUG(1, ("Could not malloc sid array\n"));
04394                 return False;
04395         }
04396 
04397         extra_data = (const char *)response.extra_data.data;
04398         i=0;
04399 
04400         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
04401 
04402                 fstring domain, user;
04403                 char *p;
04404 
04405                 fstrcpy(result[i].name, name);
04406 
04407                 p = strchr(name, *lp_winbind_separator());
04408 
04409                 DEBUG(3, ("%s\n", name));
04410 
04411                 if (p == NULL) {
04412                         fstrcpy(domain, opt_target_workgroup);
04413                         fstrcpy(user, name);
04414                 } else {
04415                         *p++ = '\0';
04416                         fstrcpy(domain, name);
04417                         strupper_m(domain);
04418                         fstrcpy(user, p);
04419                 }
04420 
04421                 get_user_sids(domain, user, &(result[i].token));
04422                 i+=1;
04423         }
04424         
04425         SAFE_FREE(response.extra_data.data);
04426 
04427         *user_tokens = result;
04428 
04429         return True;
04430 }
04431 
04432 static BOOL get_user_tokens_from_file(FILE *f,
04433                                       int *num_tokens,
04434                                       struct user_token **tokens)
04435 {
04436         struct user_token *token = NULL;
04437 
04438         while (!feof(f)) {
04439                 fstring line;
04440 
04441                 if (fgets(line, sizeof(line)-1, f) == NULL) {
04442                         return True;
04443                 }
04444 
04445                 if (line[strlen(line)-1] == '\n')
04446                         line[strlen(line)-1] = '\0';
04447 
04448                 if (line[0] == ' ') {
04449                         /* We have a SID */
04450 
04451                         DOM_SID sid;
04452                         string_to_sid(&sid, &line[1]);
04453 
04454                         if (token == NULL) {
04455                                 DEBUG(0, ("File does not begin with username"));
04456                                 return False;
04457                         }
04458 
04459                         add_sid_to_token(&token->token, &sid);
04460                         continue;
04461                 }
04462 
04463                 /* And a new user... */
04464 
04465                 *num_tokens += 1;
04466                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
04467                 if (*tokens == NULL) {
04468                         DEBUG(0, ("Could not realloc tokens\n"));
04469                         return False;
04470                 }
04471 
04472                 token = &((*tokens)[*num_tokens-1]);
04473 
04474                 fstrcpy(token->name, line);
04475                 token->token.num_sids = 0;
04476                 token->token.user_sids = NULL;
04477                 continue;
04478         }
04479         
04480         return False;
04481 }
04482 
04483 
04484 /*
04485  * Show the list of all users that have access to a share
04486  */
04487 
04488 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
04489                         TALLOC_CTX *mem_ctx,
04490                         const char *netname,
04491                         int num_tokens,
04492                         struct user_token *tokens)
04493 {
04494         int fnum;
04495         SEC_DESC *share_sd = NULL;
04496         SEC_DESC *root_sd = NULL;
04497         struct cli_state *cli = pipe_hnd->cli;
04498         int i;
04499         SRV_SHARE_INFO info;
04500         WERROR result;
04501         uint16 cnum;
04502 
04503         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname,
04504                                                502, &info);
04505 
04506         if (!W_ERROR_IS_OK(result)) {
04507                 DEBUG(1, ("Coult not query secdesc for share %s\n",
04508                           netname));
04509                 return;
04510         }
04511 
04512         share_sd = info.share.info502.info_502_str.sd;
04513         if (share_sd == NULL) {
04514                 DEBUG(1, ("Got no secdesc for share %s\n",
04515                           netname));
04516         }
04517 
04518         cnum = cli->cnum;
04519 
04520         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
04521                 return;
04522         }
04523 
04524         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
04525 
04526         if (fnum != -1) {
04527                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
04528         }
04529 
04530         for (i=0; i<num_tokens; i++) {
04531                 uint32 acc_granted;
04532                 NTSTATUS status;
04533 
04534                 if (share_sd != NULL) {
04535                         if (!se_access_check(share_sd, &tokens[i].token,
04536                                              1, &acc_granted, &status)) {
04537                                 DEBUG(1, ("Could not check share_sd for "
04538                                           "user %s\n",
04539                                           tokens[i].name));
04540                                 continue;
04541                         }
04542 
04543                         if (!NT_STATUS_IS_OK(status))
04544                                 continue;
04545                 }
04546 
04547                 if (root_sd == NULL) {
04548                         d_printf(" %s\n", tokens[i].name);
04549                         continue;
04550                 }
04551 
04552                 if (!se_access_check(root_sd, &tokens[i].token,
04553                                      1, &acc_granted, &status)) {
04554                         DEBUG(1, ("Could not check root_sd for user %s\n",
04555                                   tokens[i].name));
04556                         continue;
04557                 }
04558 
04559                 if (!NT_STATUS_IS_OK(status))
04560                         continue;
04561 
04562                 d_printf(" %s\n", tokens[i].name);
04563         }
04564 
04565         if (fnum != -1)
04566                 cli_close(cli, fnum);
04567         cli_tdis(cli);
04568         cli->cnum = cnum;
04569         
04570         return;
04571 }
04572 
04573 struct share_list {
04574         int num_shares;
04575         char **shares;
04576 };
04577 
04578 static void collect_share(const char *name, uint32 m,
04579                           const char *comment, void *state)
04580 {
04581         struct share_list *share_list = (struct share_list *)state;
04582 
04583         if (m != STYPE_DISKTREE)
04584                 return;
04585 
04586         share_list->num_shares += 1;
04587         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
04588         if (!share_list->shares) {
04589                 share_list->num_shares = 0;
04590                 return;
04591         }
04592         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
04593 }
04594 
04595 static void rpc_share_userlist_usage(void)
04596 {
04597         return;
04598 }
04599         
04600 /** 
04601  * List shares on a remote RPC server, including the security descriptors
04602  *
04603  * All parameters are provided by the run_rpc_command function, except for
04604  * argc, argv which are passes through. 
04605  *
04606  * @param domain_sid The domain sid acquired from the remote server
04607  * @param cli A cli_state connected to the server.
04608  * @param mem_ctx Talloc context, destoyed on completion of the function.
04609  * @param argc  Standard main() style argc
04610  * @param argv  Standard main() style argv.  Initial components are already
04611  *              stripped
04612  *
04613  * @return Normal NTSTATUS return.
04614  **/
04615 
04616 static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
04617                                                 const char *domain_name,
04618                                                 struct cli_state *cli,
04619                                                 struct rpc_pipe_client *pipe_hnd,
04620                                                 TALLOC_CTX *mem_ctx,
04621                                                 int argc,
04622                                                 const char **argv)
04623 {
04624         int ret;
04625         BOOL r;
04626         ENUM_HND hnd;
04627         uint32 i;
04628         FILE *f;
04629 
04630         struct user_token *tokens = NULL;
04631         int num_tokens = 0;
04632 
04633         struct share_list share_list;
04634 
04635         if (argc > 1) {
04636                 rpc_share_userlist_usage();
04637                 return NT_STATUS_UNSUCCESSFUL;
04638         }
04639 
04640         if (argc == 0) {
04641                 f = stdin;
04642         } else {
04643                 f = fopen(argv[0], "r");
04644         }
04645 
04646         if (f == NULL) {
04647                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
04648                 return NT_STATUS_UNSUCCESSFUL;
04649         }
04650 
04651         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
04652 
04653         if (f != stdin)
04654                 fclose(f);
04655 
04656         if (!r) {
04657                 DEBUG(0, ("Could not read users from file\n"));
04658                 return NT_STATUS_UNSUCCESSFUL;
04659         }
04660 
04661         for (i=0; i<num_tokens; i++)
04662                 collect_alias_memberships(&tokens[i].token);
04663 
04664         init_enum_hnd(&hnd, 0);
04665 
04666         share_list.num_shares = 0;
04667         share_list.shares = NULL;
04668 
04669         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
04670 
04671         if (ret == -1) {
04672                 DEBUG(0, ("Error returning browse list: %s\n",
04673                           cli_errstr(cli)));
04674                 goto done;
04675         }
04676 
04677         for (i = 0; i < share_list.num_shares; i++) {
04678                 char *netname = share_list.shares[i];
04679 
04680                 if (netname[strlen(netname)-1] == '$')
04681                         continue;
04682 
04683                 d_printf("%s\n", netname);
04684 
04685                 show_userlist(pipe_hnd, mem_ctx, netname,
04686                               num_tokens, tokens);
04687         }
04688  done:
04689         for (i=0; i<num_tokens; i++) {
04690                 free_user_token(&tokens[i].token);
04691         }
04692         SAFE_FREE(tokens);
04693         SAFE_FREE(share_list.shares);
04694 
04695         return NT_STATUS_OK;
04696 }
04697 
04698 static int rpc_share_allowedusers(int argc, const char **argv)
04699 {
04700         int result;
04701 
04702         result = run_rpc_command(NULL, PI_SAMR, 0,
04703                                  rpc_aliaslist_internals,
04704                                  argc, argv);
04705         if (result != 0)
04706                 return result;
04707 
04708         result = run_rpc_command(NULL, PI_LSARPC, 0,
04709                                  rpc_aliaslist_dump,
04710                                  argc, argv);
04711         if (result != 0)
04712                 return result;
04713 
04714         return run_rpc_command(NULL, PI_SRVSVC, 0,
04715                                rpc_share_allowedusers_internals,
04716                                argc, argv);
04717 }
04718 
04719 int net_usersidlist(int argc, const char **argv)
04720 {
04721         int num_tokens = 0;
04722         struct user_token *tokens = NULL;
04723         int i;
04724 
04725         if (argc != 0) {
04726                 net_usersidlist_usage(argc, argv);
04727                 return 0;
04728         }
04729 
04730         if (!get_user_tokens(&num_tokens, &tokens)) {
04731                 DEBUG(0, ("Could not get the user/sid list\n"));
04732                 return 0;
04733         }
04734 
04735         for (i=0; i<num_tokens; i++) {
04736                 dump_user_token(&tokens[i]);
04737                 free_user_token(&tokens[i].token);
04738         }
04739 
04740         SAFE_FREE(tokens);
04741         return 1;
04742 }
04743 
04744 int net_usersidlist_usage(int argc, const char **argv)
04745 {
04746         d_printf("net usersidlist\n"
04747                  "\tprints out a list of all users the running winbind knows\n"
04748                  "\tabout, together with all their SIDs. This is used as\n"
04749                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
04750 
04751         net_common_flags_usage(argc, argv);
04752         return -1;
04753 }
04754 
04755 /** 
04756  * 'net rpc share' entrypoint.
04757  * @param argc  Standard main() style argc
04758  * @param argv  Standard main() style argv.  Initial components are already
04759  *              stripped
04760  **/
04761 
04762 int net_rpc_share(int argc, const char **argv) 
04763 {
04764         struct functable func[] = {
04765                 {"add", rpc_share_add},
04766                 {"delete", rpc_share_delete},
04767                 {"allowedusers", rpc_share_allowedusers},
04768                 {"migrate", rpc_share_migrate},
04769                 {"list", rpc_share_list},
04770                 {NULL, NULL}
04771         };
04772 
04773         if (argc == 0)
04774                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
04775                                        rpc_share_list_internals,
04776                                        argc, argv);
04777 
04778         return net_run_function(argc, argv, func, rpc_share_usage);
04779 }
04780 
04781 static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
04782                                   struct rpc_sh_ctx *ctx,
04783                                   struct rpc_pipe_client *pipe_hnd,
04784                                   int argc, const char **argv)
04785 {
04786         return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
04787                                         ctx->cli, pipe_hnd, mem_ctx,
04788                                         argc, argv);
04789 }
04790 
04791 static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
04792                                  struct rpc_sh_ctx *ctx,
04793                                  struct rpc_pipe_client *pipe_hnd,
04794                                  int argc, const char **argv)
04795 {
04796         WERROR result;
04797 
04798         if ((argc < 2) || (argc > 3)) {
04799                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
04800                           ctx->whoami);
04801                 return NT_STATUS_INVALID_PARAMETER;
04802         }
04803 
04804         result = rpccli_srvsvc_net_share_add(
04805                 pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
04806                 (argc == 3) ? argv[2] : "",
04807                 0, 0, 0, argv[1], NULL, 2, NULL);
04808                                              
04809         return werror_to_ntstatus(result);
04810 }
04811 
04812 static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
04813                                     struct rpc_sh_ctx *ctx,
04814                                     struct rpc_pipe_client *pipe_hnd,
04815                                     int argc, const char **argv)
04816 {
04817         WERROR result;
04818 
04819         if (argc != 1) {
04820                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
04821                 return NT_STATUS_INVALID_PARAMETER;
04822         }
04823 
04824         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
04825         return werror_to_ntstatus(result);
04826 }
04827 
04828 static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
04829                                   struct rpc_sh_ctx *ctx,
04830                                   struct rpc_pipe_client *pipe_hnd,
04831                                   int argc, const char **argv)
04832 {
04833         SRV_SHARE_INFO info;
04834         SRV_SHARE_INFO_2 *info2 = &info.share.info2;
04835         WERROR result;
04836 
04837         if (argc != 1) {
04838                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
04839                 return NT_STATUS_INVALID_PARAMETER;
04840         }
04841 
04842         result = rpccli_srvsvc_net_share_get_info(
04843                 pipe_hnd, mem_ctx, argv[0], 2, &info);
04844         if (!W_ERROR_IS_OK(result)) {
04845                 goto done;
04846         }
04847 
04848         d_printf("Name:     %s\n",
04849                  rpcstr_pull_unistr2_talloc(mem_ctx,
04850                                             &info2->info_2_str.uni_netname));
04851         d_printf("Comment:  %s\n",
04852                  rpcstr_pull_unistr2_talloc(mem_ctx,
04853                                             &info2->info_2_str.uni_remark));
04854         
04855         d_printf("Path:     %s\n",
04856                  rpcstr_pull_unistr2_talloc(mem_ctx,
04857                                             &info2->info_2_str.uni_path));
04858         d_printf("Password: %s\n",
04859                  rpcstr_pull_unistr2_talloc(mem_ctx,
04860                                             &info2->info_2_str.uni_passwd));
04861 
04862  done:
04863         return werror_to_ntstatus(result);
04864 }
04865 
04866 struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
04867                                       struct rpc_sh_ctx *ctx)
04868 {
04869         static struct rpc_sh_cmd cmds[] = {
04870 
04871         { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
04872           "List available shares" },
04873 
04874         { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
04875           "Add a share" },
04876 
04877         { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
04878           "Delete a share" },
04879 
04880         { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
04881           "Get information about a share" },
04882 
04883         { NULL, NULL, 0, NULL, NULL }
04884         };
04885 
04886         return cmds;
04887 }
04888 
04889 /****************************************************************************/
04890 
04891 static int rpc_file_usage(int argc, const char **argv)
04892 {
04893         return net_help_file(argc, argv);
04894 }
04895 
04896 /** 
04897  * Close a file on a remote RPC server
04898  *
04899  * All parameters are provided by the run_rpc_command function, except for
04900  * argc, argv which are passes through. 
04901  *
04902  * @param domain_sid The domain sid acquired from the remote server
04903  * @param cli A cli_state connected to the server.
04904  * @param mem_ctx Talloc context, destoyed on completion of the function.
04905  * @param argc  Standard main() style argc
04906  * @param argv  Standard main() style argv.  Initial components are already
04907  *              stripped
04908  *
04909  * @return Normal NTSTATUS return.
04910  **/
04911 static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
04912                                         const char *domain_name, 
04913                                         struct cli_state *cli,
04914                                         struct rpc_pipe_client *pipe_hnd,
04915                                         TALLOC_CTX *mem_ctx,
04916                                         int argc,
04917                                         const char **argv)
04918 {
04919         WERROR result;
04920         result = rpccli_srvsvc_net_file_close(pipe_hnd, mem_ctx, atoi(argv[0]));
04921         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
04922 }
04923 
04924 /** 
04925  * Close a file on a remote RPC server
04926  *
04927  * @param argc  Standard main() style argc
04928  * @param argv  Standard main() style argv.  Initial components are already
04929  *              stripped
04930  *
04931  * @return A shell status integer (0 for success)
04932  **/
04933 static int rpc_file_close(int argc, const char **argv)
04934 {
04935         if (argc < 1) {
04936                 DEBUG(1, ("No fileid given on close\n"));
04937                 return(rpc_file_usage(argc, argv));
04938         }
04939 
04940         return run_rpc_command(NULL, PI_SRVSVC, 0, 
04941                                rpc_file_close_internals,
04942                                argc, argv);
04943 }
04944 
04945 /** 
04946  * Formatted print of open file info 
04947  *
04948  * @param info3  FILE_INFO_3 contents
04949  * @param str3   strings for FILE_INFO_3
04950  **/
04951 
04952 static void display_file_info_3( FILE_INFO_3 *info3 )
04953 {
04954         fstring user = "", path = "";
04955 
04956         rpcstr_pull_unistr2_fstring(user, info3->user);
04957         rpcstr_pull_unistr2_fstring(path, info3->path);
04958 
04959         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
04960                  info3->id, user, info3->perms, info3->num_locks, path);
04961 }
04962 
04963 /** 
04964  * List open files on a remote RPC server
04965  *
04966  * All parameters are provided by the run_rpc_command function, except for
04967  * argc, argv which are passes through. 
04968  *
04969  * @param domain_sid The domain sid acquired from the remote server
04970  * @param cli A cli_state connected to the server.
04971  * @param mem_ctx Talloc context, destoyed on completion of the function.
04972  * @param argc  Standard main() style argc
04973  * @param argv  Standard main() style argv.  Initial components are already
04974  *              stripped
04975  *
04976  * @return Normal NTSTATUS return.
04977  **/
04978 
04979 static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
04980                                         const char *domain_name, 
04981                                         struct cli_state *cli,
04982                                         struct rpc_pipe_client *pipe_hnd,
04983                                         TALLOC_CTX *mem_ctx,
04984                                         int argc,
04985                                         const char **argv)
04986 {
04987         SRV_FILE_INFO_CTR ctr;
04988         WERROR result;
04989         ENUM_HND hnd;
04990         uint32 preferred_len = 0xffffffff, i;
04991         const char *username=NULL;
04992 
04993         init_enum_hnd(&hnd, 0);
04994 
04995         /* if argc > 0, must be user command */
04996         if (argc > 0)
04997                 username = smb_xstrdup(argv[0]);
04998                 
04999         result = rpccli_srvsvc_net_file_enum(pipe_hnd,
05000                                         mem_ctx, 3, username, &ctr, preferred_len, &hnd);
05001 
05002         if (!W_ERROR_IS_OK(result))
05003                 goto done;
05004 
05005         /* Display results */
05006 
05007         d_printf(
05008                  "\nEnumerating open files on remote server:\n\n"\
05009                  "\nFileId  Opened by            Perms  Locks  Path"\
05010                  "\n------  ---------            -----  -----  ---- \n");
05011         for (i = 0; i < ctr.num_entries; i++)
05012                 display_file_info_3(&ctr.file.info3[i]);
05013  done:
05014         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
05015 }
05016 
05017 /** 
05018  * List files for a user on a remote RPC server
05019  *
05020  * @param argc  Standard main() style argc
05021  * @param argv  Standard main() style argv.  Initial components are already
05022  *              stripped
05023  *
05024  * @return A shell status integer (0 for success)
05025  **/
05026 
05027 static int rpc_file_user(int argc, const char **argv)
05028 {
05029         if (argc < 1) {
05030                 DEBUG(1, ("No username given\n"));
05031                 return(rpc_file_usage(argc, argv));
05032         }
05033 
05034         return run_rpc_command(NULL, PI_SRVSVC, 0, 
05035                                rpc_file_list_internals,
05036                                argc, argv);
05037 }
05038 
05039 /** 
05040  * 'net rpc file' entrypoint.
05041  * @param argc  Standard main() style argc
05042  * @param argv  Standard main() style argv.  Initial components are already
05043  *              stripped
05044  **/
05045 
05046 int net_rpc_file(int argc, const char **argv) 
05047 {
05048         struct functable func[] = {
05049                 {"close", rpc_file_close},
05050                 {"user", rpc_file_user},
05051 #if 0
05052                 {"info", rpc_file_info},
05053 #endif
05054                 {NULL, NULL}
05055         };
05056 
05057         if (argc == 0)
05058                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
05059                                        rpc_file_list_internals,
05060                                        argc, argv);
05061 
05062         return net_run_function(argc, argv, func, rpc_file_usage);
05063 }
05064 
05065 /** 
05066  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
05067  *
05068  * All parameters are provided by the run_rpc_command function, except for
05069  * argc, argv which are passed through. 
05070  *
05071  * @param domain_sid The domain sid aquired from the remote server
05072  * @param cli A cli_state connected to the server.
05073  * @param mem_ctx Talloc context, destoyed on compleation of the function.
05074  * @param argc  Standard main() style argc
05075  * @param argv  Standard main() style argv.  Initial components are already
05076  *              stripped
05077  *
05078  * @return Normal NTSTATUS return.
05079  **/
05080 
05081 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
05082                                         const char *domain_name, 
05083                                         struct cli_state *cli, 
05084                                         struct rpc_pipe_client *pipe_hnd,
05085                                         TALLOC_CTX *mem_ctx, 
05086                                         int argc,
05087                                         const char **argv) 
05088 {
05089         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
05090         
05091         result = rpccli_shutdown_abort(pipe_hnd, mem_ctx);
05092         
05093         if (NT_STATUS_IS_OK(result)) {
05094                 d_printf("\nShutdown successfully aborted\n");
05095                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
05096         } else
05097                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
05098         
05099         return result;
05100 }
05101 
05102 /** 
05103  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
05104  *
05105  * All parameters are provided by the run_rpc_command function, except for
05106  * argc, argv which are passed through. 
05107  *
05108  * @param domain_sid The domain sid aquired from the remote server
05109  * @param cli A cli_state connected to the server.
05110  * @param mem_ctx Talloc context, destoyed on compleation of the function.
05111  * @param argc  Standard main() style argc
05112  * @param argv  Standard main() style argv.  Initial components are already
05113  *              stripped
05114  *
05115  * @return Normal NTSTATUS return.
05116  **/
05117 
05118 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
05119                                                 const char *domain_name, 
05120                                                 struct cli_state *cli, 
05121                                                 struct rpc_pipe_client *pipe_hnd,
05122                                                 TALLOC_CTX *mem_ctx, 
05123                                                 int argc,
05124                                                 const char **argv) 
05125 {
05126         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
05127         
05128         result = werror_to_ntstatus(rpccli_reg_abort_shutdown(pipe_hnd, mem_ctx));
05129         
05130         if (NT_STATUS_IS_OK(result)) {
05131                 d_printf("\nShutdown successfully aborted\n");
05132                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
05133         } else
05134                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
05135         
05136         return result;
05137 }
05138 
05139 /** 
05140  * ABORT the Shut down of a remote RPC server
05141  *
05142  * @param argc  Standard main() style argc
05143  * @param argv  Standard main() style argv.  Initial components are already
05144  *              stripped
05145  *
05146  * @return A shell status integer (0 for success)
05147  **/
05148 
05149 static int rpc_shutdown_abort(int argc, const char **argv) 
05150 {
05151         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
05152                                  rpc_shutdown_abort_internals,
05153                                  argc, argv);
05154 
05155         if (rc == 0)
05156                 return rc;
05157 
05158         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
05159 
05160         return run_rpc_command(NULL, PI_WINREG, 0, 
05161                                rpc_reg_shutdown_abort_internals,
05162                                argc, argv);
05163 }
05164 
05165 /** 
05166  * Shut down a remote RPC Server via initshutdown pipe
05167  *
05168  * All parameters are provided by the run_rpc_command function, except for
05169  * argc, argv which are passes through. 
05170  *
05171  * @param domain_sid The domain sid aquired from the remote server
05172  * @param cli A cli_state connected to the server.
05173  * @param mem_ctx Talloc context, destoyed on compleation of the function.
05174  * @param argc  Standard main() style argc
05175  * @param argc  Standard main() style argv.  Initial components are already
05176  *              stripped
05177  *
05178  * @return Normal NTSTATUS return.
05179  **/
05180 
05181 static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, 
05182                                                 const char *domain_name, 
05183                                                 struct cli_state *cli, 
05184                                                 struct rpc_pipe_client *pipe_hnd,
05185                                                 TALLOC_CTX *mem_ctx, 
05186                                                 int argc,
05187                                                 const char **argv) 
05188 {
05189         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
05190         const char *msg = "This machine will be shutdown shortly";
05191         uint32 timeout = 20;
05192 
05193         if (opt_comment) {
05194                 msg = opt_comment;
05195         }
05196         if (opt_timeout) {
05197                 timeout = opt_timeout;
05198         }
05199 
05200         /* create an entry */
05201         result = rpccli_shutdown_init(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, 
05202                                    opt_force);
05203 
05204         if (NT_STATUS_IS_OK(result)) {
05205                 d_printf("\nShutdown of remote machine succeeded\n");
05206                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
05207         } else {
05208                 DEBUG(1,("Shutdown of remote machine failed!\n"));
05209         }
05210         return result;
05211 }
05212 
05213 /** 
05214  * Shut down a remote RPC Server via winreg pipe
05215  *
05216  * All parameters are provided by the run_rpc_command function, except for
05217  * argc, argv which are passes through. 
05218  *
05219  * @param domain_sid The domain sid aquired from the remote server
05220  * @param cli A cli_state connected to the server.
05221  * @param mem_ctx Talloc context, destoyed on compleation of the function.
05222  * @param argc  Standard main() style argc
05223  * @param argc  Standard main() style argv.  Initial components are already
05224  *              stripped
05225  *
05226  * @return Normal NTSTATUS return.
05227  **/
05228 
05229 static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid, 
05230                                                 const char *domain_name, 
05231                                                 struct cli_state *cli, 
05232                                                 struct rpc_pipe_client *pipe_hnd,
05233                                                 TALLOC_CTX *mem_ctx, 
05234                                                 int argc,
05235                                                 const char **argv) 
05236 {
05237         WERROR result;
05238         const char *msg = "This machine will be shutdown shortly";
05239         uint32 timeout = 20;
05240 #if 0
05241         poptContext pc;
05242         int rc;
05243 
05244         struct poptOption long_options[] = {
05245                 {"message",    'm', POPT_ARG_STRING, &msg},
05246                 {"timeout",    't', POPT_ARG_INT,    &timeout},
05247                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
05248                 {"force",      'f', POPT_ARG_NONE,   &force},
05249                 { 0, 0, 0, 0}
05250         };
05251 
05252         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
05253                             POPT_CONTEXT_KEEP_FIRST);
05254 
05255         rc = poptGetNextOpt(pc);
05256         
05257         if (rc < -1) {
05258                 /* an error occurred during option processing */
05259                 DEBUG(0, ("%s: %s\n",
05260                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
05261                           poptStrerror(rc)));
05262                 return NT_STATUS_INVALID_PARAMETER;
05263         }
05264 #endif
05265         if (opt_comment) {
05266                 msg = opt_comment;
05267         }
05268         if (opt_timeout) {
05269                 timeout = opt_timeout;
05270         }
05271 
05272         /* create an entry */
05273         result = rpccli_reg_shutdown(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, opt_force);
05274 
05275         if (W_ERROR_IS_OK(result)) {
05276                 d_printf("\nShutdown of remote machine succeeded\n");
05277         } else {
05278                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
05279                 if (W_ERROR_EQUAL(result,WERR_MACHINE_LOCKED))
05280                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
05281                 else
05282                         d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(result));
05283         }
05284 
05285         return werror_to_ntstatus(result);
05286 }
05287 
05288 /** 
05289  * Shut down a remote RPC server
05290  *
05291  * @param argc  Standard main() style argc
05292  * @param argc  Standard main() style argv.  Initial components are already
05293  *              stripped
05294  *
05295  * @return A shell status integer (0 for success)
05296  **/
05297 
05298 static int rpc_shutdown(int argc, const char **argv) 
05299 {
05300         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
05301                                  rpc_init_shutdown_internals,
05302                                  argc, argv);
05303 
05304         if (rc) {
05305                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
05306                 rc = run_rpc_command(NULL, PI_WINREG, 0, 
05307                                      rpc_reg_shutdown_internals, argc, argv);
05308         }
05309 
05310         return rc;
05311 }
05312 
05313 /***************************************************************************
05314   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
05315   
05316  ***************************************************************************/
05317 
05318 /**
05319  * Add interdomain trust account to the RPC server.
05320  * All parameters (except for argc and argv) are passed by run_rpc_command
05321  * function.
05322  *
05323  * @param domain_sid The domain sid acquired from the server
05324  * @param cli A cli_state connected to the server.
05325  * @param mem_ctx Talloc context, destoyed on completion of the function.
05326  * @param argc  Standard main() style argc
05327  * @param argc  Standard main() style argv.  Initial components are already
05328  *              stripped
05329  *
05330  * @return normal NTSTATUS return code
05331  */
05332 
05333 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
05334                                                 const char *domain_name, 
05335                                                 struct cli_state *cli,
05336                                                 struct rpc_pipe_client *pipe_hnd,
05337                                                 TALLOC_CTX *mem_ctx, 
05338                                                 int argc,
05339                                                 const char **argv)
05340 {
05341         POLICY_HND connect_pol, domain_pol, user_pol;
05342         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
05343         char *acct_name;
05344         uint32 acb_info;
05345         uint32 user_rid;
05346         uint32 acct_flags=0;
05347 
05348         if (argc != 2) {
05349                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
05350                 return NT_STATUS_INVALID_PARAMETER;
05351         }
05352 
05353         /* 
05354          * Make valid trusting domain account (ie. uppercased and with '$' appended)
05355          */
05356          
05357         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
05358                 return NT_STATUS_NO_MEMORY;
05359         }
05360 
05361         strupper_m(acct_name);
05362 
05363         /* Get samr policy handle */
05364         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
05365                                   &connect_pol);
05366         if (!NT_STATUS_IS_OK(result)) {
05367                 goto done;
05368         }
05369         
05370         /* Get domain policy handle */
05371         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
05372                                       MAXIMUM_ALLOWED_ACCESS,
05373                                       domain_sid, &domain_pol);
05374         if (!NT_STATUS_IS_OK(result)) {
05375                 goto done;
05376         }
05377 
05378         /* Create trusting domain's account */
05379         acb_info = ACB_NORMAL; 
05380         acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
05381                 SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
05382                 SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
05383                 SAMR_USER_SETATTR;
05384 
05385         result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
05386                                           acct_name, acb_info, acct_flags,
05387                                           &user_pol, &user_rid);
05388         if (!NT_STATUS_IS_OK(result)) {
05389                 goto done;
05390         }
05391 
05392         {
05393                 SAM_USERINFO_CTR ctr;
05394                 SAM_USER_INFO_23 p23;
05395                 NTTIME notime;
05396                 char nostr[] = "";
05397                 LOGON_HRS hrs;
05398                 uchar pwbuf[516];
05399 
05400                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
05401 
05402                 ZERO_STRUCT(ctr);
05403                 ZERO_STRUCT(p23);
05404                 ZERO_STRUCT(notime);
05405                 hrs.max_len = 1260;
05406                 hrs.offset = 0;
05407                 hrs.len = 21;
05408                 memset(hrs.hours, 0xFF, sizeof(hrs.hours));
05409                 acb_info = ACB_DOMTRUST;
05410 
05411                 init_sam_user_info23A(&p23, &notime, &notime, &notime,
05412                                       &notime, &notime, &notime,
05413                                       nostr, nostr, nostr, nostr, nostr,
05414                                       nostr, nostr, nostr, nostr, nostr,
05415                                       0, 0, acb_info, ACCT_FLAGS, 168, &hrs, 
05416                                       0, 0, (char *)pwbuf);
05417                 ctr.switch_value = 23;
05418                 ctr.info.id23 = &p23;
05419                 p23.passmustchange = 0;
05420 
05421                 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 23,
05422                                                &cli->user_session_key, &ctr);
05423 
05424                 if (!NT_STATUS_IS_OK(result)) {
05425                         DEBUG(0,("Could not set trust account password: %s\n",
05426                                  nt_errstr(result)));
05427                         goto done;
05428                 }
05429         }
05430 
05431  done:
05432         SAFE_FREE(acct_name);
05433         return result;
05434 }
05435 
05436 /**
05437  * Create interdomain trust account for a remote domain.
05438  *
05439  * @param argc standard argc
05440  * @param argv standard argv without initial components
05441  *
05442  * @return Integer status (0 means success)
05443  **/
05444 
05445 static int rpc_trustdom_add(int argc, const char **argv)
05446 {
05447         if (argc > 0) {
05448                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
05449                                        argc, argv);
05450         } else {
05451                 d_printf("Usage: net rpc trustdom add <domain> <trust password>\n");
05452                 return -1;
05453         }
05454 }
05455 
05456 
05457 /**
05458  * Remove interdomain trust account from the RPC server.
05459  * All parameters (except for argc and argv) are passed by run_rpc_command
05460  * function.
05461  *
05462  * @param domain_sid The domain sid acquired from the server
05463  * @param cli A cli_state connected to the server.
05464  * @param mem_ctx Talloc context, destoyed on completion of the function.
05465  * @param argc  Standard main() style argc
05466  * @param argc  Standard main() style argv.  Initial components are already
05467  *              stripped
05468  *
05469  * @return normal NTSTATUS return code
05470  */
05471 
05472 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
05473                                         const char *domain_name, 
05474                                         struct cli_state *cli,
05475                                         struct rpc_pipe_client *pipe_hnd,
05476                                         TALLOC_CTX *mem_ctx, 
05477                                         int argc,
05478                                         const char **argv)
05479 {
05480         POLICY_HND connect_pol, domain_pol, user_pol;
05481         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
05482         char *acct_name;
05483         const char **names;
05484         DOM_SID trust_acct_sid;
05485         uint32 *user_rids, num_rids, *name_types;
05486         uint32 flags = 0x000003e8; /* Unknown */
05487 
05488         if (argc != 1) {
05489                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
05490                 return NT_STATUS_INVALID_PARAMETER;
05491         }
05492 
05493         /* 
05494          * Make valid trusting domain account (ie. uppercased and with '$' appended)
05495          */
05496         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
05497 
05498         if (acct_name == NULL)
05499                 return NT_STATUS_NO_MEMORY;
05500 
05501         strupper_m(acct_name);
05502 
05503         if ((names = TALLOC_ARRAY(mem_ctx, const char *, 1)) == NULL) {
05504                 return NT_STATUS_NO_MEMORY;
05505         }
05506         names[0] = acct_name;
05507 
05508 
05509         /* Get samr policy handle */
05510         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
05511                                   &connect_pol);
05512         if (!NT_STATUS_IS_OK(result)) {
05513                 goto done;
05514         }
05515         
05516         /* Get domain policy handle */
05517         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
05518                                       MAXIMUM_ALLOWED_ACCESS,
05519                                       domain_sid, &domain_pol);
05520         if (!NT_STATUS_IS_OK(result)) {
05521                 goto done;
05522         }
05523 
05524         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1,
05525                                        names, &num_rids,
05526                                        &user_rids, &name_types);
05527         
05528         if (!NT_STATUS_IS_OK(result)) {
05529                 goto done;
05530         }
05531 
05532         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
05533                                     MAXIMUM_ALLOWED_ACCESS,
05534                                     user_rids[0], &user_pol);
05535 
05536         if (!NT_STATUS_IS_OK(result)) {
05537                 goto done;
05538         }
05539 
05540         /* append the rid to the domain sid */
05541         sid_copy(&trust_acct_sid, domain_sid);
05542         if (!sid_append_rid(&trust_acct_sid, user_rids[0])) {
05543                 goto done;
05544         }
05545 
05546         /* remove the sid */
05547 
05548         result = rpccli_samr_remove_sid_foreign_domain(pipe_hnd, mem_ctx, &user_pol,
05549                                                     &trust_acct_sid);
05550 
05551         if (!NT_STATUS_IS_OK(result)) {
05552                 goto done;
05553         }
05554 
05555         /* Delete user */
05556 
05557         result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
05558 
05559         if (!NT_STATUS_IS_OK(result)) {
05560                 goto done;
05561         }
05562 
05563         if (!NT_STATUS_IS_OK(result)) {
05564           DEBUG(0,("Could not set trust account password: %s\n",
05565                    nt_errstr(result)));
05566           goto done;
05567         }
05568 
05569  done:
05570         return result;
05571 }
05572 
05573 /**
05574  * Delete interdomain trust account for a remote domain.
05575  *
05576  * @param argc standard argc
05577  * @param argv standard argv without initial components
05578  *
05579  * @return Integer status (0 means success)
05580  **/
05581 
05582 static int rpc_trustdom_del(int argc, const char **argv)
05583 {
05584         if (argc > 0) {
05585                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
05586                                        argc, argv);
05587         } else {
05588                 d_printf("Usage: net rpc trustdom del <domain>\n");
05589                 return -1;
05590         }
05591 }
05592  
05593 
05594 /**
05595  * Establish trust relationship to a trusting domain.
05596  * Interdomain account must already be created on remote PDC.
05597  *
05598  * @param argc standard argc
05599  * @param argv standard argv without initial components
05600  *
05601  * @return Integer status (0 means success)
05602  **/
05603 
05604 static int rpc_trustdom_establish(int argc, const char **argv)
05605 {
05606         struct cli_state *cli = NULL;
05607         struct in_addr server_ip;
05608         struct rpc_pipe_client *pipe_hnd = NULL;
05609         POLICY_HND connect_hnd;
05610         TALLOC_CTX *mem_ctx;
05611         NTSTATUS nt_status;
05612         DOM_SID *domain_sid;
05613         
05614         char* domain_name;
05615         char* domain_name_pol;
05616         char* acct_name;
05617         fstring pdc_name;
05618 
05619         /*
05620          * Connect to \\server\ipc$ as 'our domain' account with password
05621          */
05622 
05623         if (argc != 1) {
05624                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
05625                 return -1;
05626         }
05627 
05628         domain_name = smb_xstrdup(argv[0]);
05629         strupper_m(domain_name);
05630 
05631         /* account name used at first is our domain's name with '$' */
05632         asprintf(&acct_name, "%s$", lp_workgroup());
05633         strupper_m(acct_name);
05634         
05635         /*
05636          * opt_workgroup will be used by connection functions further,
05637          * hence it should be set to remote domain name instead of ours
05638          */
05639         if (opt_workgroup) {
05640                 opt_workgroup = smb_xstrdup(domain_name);
05641         };
05642         
05643         opt_user_name = acct_name;
05644 
05645         /* find the domain controller */
05646         if (!net_find_pdc(&server_ip, pdc_name, domain_name)) {
05647                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
05648                 return -1;
05649         }
05650 
05651         /* connect to ipc$ as username/password */
05652         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
05653         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
05654 
05655                 /* Is it trusting domain account for sure ? */
05656                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
05657                         nt_errstr(nt_status)));
05658                 return -1;
05659         }
05660 
05661         /* store who we connected to */
05662 
05663         saf_store( domain_name, pdc_name );
05664         
05665         /*
05666          * Connect to \\server\ipc$ again (this time anonymously)
05667          */
05668         
05669         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
05670         
05671         if (NT_STATUS_IS_ERR(nt_status)) {
05672                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
05673                         domain_name, nt_errstr(nt_status)));
05674                 return -1;
05675         }
05676 
05677         /*
05678          * Use NetServerEnum2 to make sure we're talking to a proper server
05679          */
05680          
05681         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
05682                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
05683                          for domain %s\n", domain_name));
05684                 cli_shutdown(cli);
05685                 return -1;
05686         }
05687          
05688         if (!(mem_ctx = talloc_init("establishing trust relationship to "
05689                                     "domain %s", domain_name))) {
05690                 DEBUG(0, ("talloc_init() failed\n"));
05691                 cli_shutdown(cli);
05692                 return -1;
05693         }
05694 
05695         /*
05696          * Call LsaOpenPolicy and LsaQueryInfo
05697          */
05698          
05699         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
05700         if (!pipe_hnd) {
05701                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
05702                 cli_shutdown(cli);
05703                 talloc_destroy(mem_ctx);
05704                 return -1;
05705         }
05706 
05707         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
05708                                          &connect_hnd);
05709         if (NT_STATUS_IS_ERR(nt_status)) {
05710                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
05711                         nt_errstr(nt_status)));
05712                 cli_shutdown(cli);
05713                 talloc_destroy(mem_ctx);
05714                 return -1;
05715         }
05716 
05717         /* Querying info level 5 */
05718         
05719         nt_status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &connect_hnd,
05720                                               5 /* info level */,
05721                                               &domain_name_pol, &domain_sid);
05722         if (NT_STATUS_IS_ERR(nt_status)) {
05723                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
05724                         nt_errstr(nt_status)));
05725                 cli_shutdown(cli);
05726                 talloc_destroy(mem_ctx);
05727                 return -1;
05728         }
05729 
05730         /* There should be actually query info level 3 (following nt serv behaviour),
05731            but I still don't know if it's _really_ necessary */
05732                         
05733         /*
05734          * Store the password in secrets db
05735          */
05736 
05737         if (!secrets_store_trusted_domain_password(domain_name,
05738                                                    opt_password,
05739                                                    domain_sid)) {
05740                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
05741                 cli_shutdown(cli);
05742                 talloc_destroy(mem_ctx);
05743                 return -1;
05744         }
05745         
05746         /*
05747          * Close the pipes and clean up
05748          */
05749          
05750         nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
05751         if (NT_STATUS_IS_ERR(nt_status)) {
05752                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
05753                         nt_errstr(nt_status)));
05754                 cli_shutdown(cli);
05755                 talloc_destroy(mem_ctx);
05756                 return -1;
05757         }
05758 
05759         cli_shutdown(cli);
05760          
05761         talloc_destroy(mem_ctx);
05762          
05763         d_printf("Trust to domain %s established\n", domain_name);
05764         return 0;
05765 }
05766 
05767 /**
05768  * Revoke trust relationship to the remote domain
05769  *
05770  * @param argc standard argc
05771  * @param argv standard argv without initial components
05772  *
05773  * @return Integer status (0 means success)
05774  **/
05775 
05776 static int rpc_trustdom_revoke(int argc, const char **argv)
05777 {
05778         char* domain_name;
05779 
05780         if (argc < 1) return -1;
05781         
05782         /* generate upper cased domain name */
05783         domain_name = smb_xstrdup(argv[0]);
05784         strupper_m(domain_name);
05785 
05786         /* delete password of the trust */
05787         if (!trusted_domain_password_delete(domain_name)) {
05788                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
05789                           domain_name));
05790                 return -1;
05791         };
05792         
05793         return 0;
05794 }
05795 
05796 /**
05797  * Usage for 'net rpc trustdom' command
05798  *
05799  * @param argc standard argc
05800  * @param argv standard argv without inital components
05801  *
05802  * @return Integer status returned to shell
05803  **/
05804  
05805 static int rpc_trustdom_usage(int argc, const char **argv)
05806 {
05807         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
05808         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
05809         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
05810         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
05811         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
05812         d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
05813         return -1;
05814 }
05815 
05816 
05817 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
05818                                         const char *domain_name, 
05819                                         struct cli_state *cli,
05820                                         struct rpc_pipe_client *pipe_hnd,
05821                                         TALLOC_CTX *mem_ctx,
05822                                         int argc,
05823                                         const char **argv)
05824 {
05825         fstring str_sid;
05826         sid_to_string(str_sid, domain_sid);
05827         d_printf("%s\n", str_sid);
05828         return NT_STATUS_OK;
05829 }
05830 
05831 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
05832 {
05833         fstring ascii_sid, padding;
05834         int pad_len, col_len = 20;
05835 
05836         /* convert sid into ascii string */
05837         sid_to_string(ascii_sid, dom_sid);
05838 
05839         /* calculate padding space for d_printf to look nicer */
05840         pad_len = col_len - strlen(trusted_dom_name);
05841         padding[pad_len] = 0;
05842         do padding[--pad_len] = ' '; while (pad_len);
05843                         
05844         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
05845 }
05846 
05847 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
05848                                       TALLOC_CTX *mem_ctx, 
05849                                       POLICY_HND *pol, 
05850                                       DOM_SID dom_sid, 
05851                                       const char *trusted_dom_name)
05852 {
05853         NTSTATUS nt_status;
05854         LSA_TRUSTED_DOMAIN_INFO *info;
05855         char *cleartextpwd = NULL;
05856         DATA_BLOB data;
05857 
05858         nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info);
05859         
05860         if (NT_STATUS_IS_ERR(nt_status)) {
05861                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
05862                 nt_errstr(nt_status)));
05863                 goto done;
05864         }
05865 
05866         data = data_blob(NULL, info->password.password.length);
05867 
05868         memcpy(data.data, info->password.password.data, info->password.password.length);
05869         data.length     = info->password.password.length;
05870                                 
05871         cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password, &data);
05872 
05873         if (cleartextpwd == NULL) {
05874                 DEBUG(0,("retrieved NULL password\n"));
05875                 nt_status = NT_STATUS_UNSUCCESSFUL;
05876                 goto done;
05877         }
05878         
05879         if (!secrets_store_trusted_domain_password(trusted_dom_name,
05880                                                    cleartextpwd,
05881                                                    &dom_sid)) {
05882                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
05883                 nt_status = NT_STATUS_UNSUCCESSFUL;
05884                 goto done;
05885         }
05886 
05887 #ifdef DEBUG_PASSWORD
05888         DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], password: [%s]\n",  
05889                 trusted_dom_name, sid_string_static(&dom_sid), cleartextpwd));
05890 #endif
05891 
05892 done:
05893         SAFE_FREE(cleartextpwd);
05894         data_blob_free(&data);
05895 
05896         return nt_status;
05897 }
05898 
05899 static int rpc_trustdom_vampire(int argc, const char **argv)
05900 {
05901         /* common variables */
05902         TALLOC_CTX* mem_ctx;
05903         struct cli_state *cli = NULL;
05904         struct rpc_pipe_client *pipe_hnd = NULL;
05905         NTSTATUS nt_status;
05906         const char *domain_name = NULL;
05907         DOM_SID *queried_dom_sid;
05908         POLICY_HND connect_hnd;
05909 
05910         /* trusted domains listing variables */
05911         unsigned int num_domains, enum_ctx = 0;
05912         int i;
05913         DOM_SID *domain_sids;
05914         char **trusted_dom_names;
05915         fstring pdc_name;
05916         char *dummy;
05917 
05918         /*
05919          * Listing trusted domains (stored in secrets.tdb, if local)
05920          */
05921 
05922         mem_ctx = talloc_init("trust relationships vampire");
05923 
05924         /*
05925          * set domain and pdc name to local samba server (default)
05926          * or to remote one given in command line
05927          */
05928 
05929         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
05930                 domain_name = opt_workgroup;
05931                 opt_target_workgroup = opt_workgroup;
05932         } else {
05933                 fstrcpy(pdc_name, global_myname());
05934                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
05935                 opt_target_workgroup = domain_name;
05936         };
05937 
05938         /* open \PIPE\lsarpc and open policy handle */
05939         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
05940                 DEBUG(0, ("Couldn't connect to domain controller\n"));
05941                 talloc_destroy(mem_ctx);
05942                 return -1;
05943         };
05944 
05945         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
05946         if (!pipe_hnd) {
05947                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
05948                         nt_errstr(nt_status) ));
05949                 cli_shutdown(cli);
05950                 talloc_destroy(mem_ctx);
05951                 return -1;
05952         };
05953 
05954         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
05955                                         &connect_hnd);
05956         if (NT_STATUS_IS_ERR(nt_status)) {
05957                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
05958                         nt_errstr(nt_status)));
05959                 cli_shutdown(cli);
05960                 talloc_destroy(mem_ctx);
05961                 return -1;
05962         };
05963 
05964         /* query info level 5 to obtain sid of a domain being queried */
05965         nt_status = rpccli_lsa_query_info_policy(
05966                 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
05967                 &dummy, &queried_dom_sid);
05968 
05969         if (NT_STATUS_IS_ERR(nt_status)) {
05970                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
05971                         nt_errstr(nt_status)));
05972                 cli_shutdown(cli);
05973                 talloc_destroy(mem_ctx);
05974                 return -1;
05975         }
05976 
05977         /*
05978          * Keep calling LsaEnumTrustdom over opened pipe until
05979          * the end of enumeration is reached
05980          */
05981 
05982         d_printf("Vampire trusted domains:\n\n");
05983 
05984         do {
05985                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
05986                                                    &num_domains,
05987                                                    &trusted_dom_names, &domain_sids);
05988                 
05989                 if (NT_STATUS_IS_ERR(nt_status)) {
05990                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
05991                                 nt_errstr(nt_status)));
05992                         cli_shutdown(cli);
05993                         talloc_destroy(mem_ctx);
05994                         return -1;
05995                 };
05996                 
05997                 for (i = 0; i < num_domains; i++) {
05998 
05999                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
06000 
06001                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
06002                                                            domain_sids[i], trusted_dom_names[i]);
06003                         if (!NT_STATUS_IS_OK(nt_status)) {
06004                                 cli_shutdown(cli);
06005                                 talloc_destroy(mem_ctx);
06006                                 return -1;
06007                         }
06008                 };
06009 
06010                 /*
06011                  * in case of no trusted domains say something rather
06012                  * than just display blank line
06013                  */
06014                 if (!num_domains) d_printf("none\n");
06015 
06016         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
06017 
06018         /* close this connection before doing next one */
06019         nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
06020         if (NT_STATUS_IS_ERR(nt_status)) {
06021                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
06022                         nt_errstr(nt_status)));
06023                 cli_shutdown(cli);
06024                 talloc_destroy(mem_ctx);
06025                 return -1;
06026         };
06027 
06028         /* close lsarpc pipe and connection to IPC$ */
06029         cli_shutdown(cli);
06030 
06031         talloc_destroy(mem_ctx);         
06032         return 0;
06033 }
06034 
06035 static int rpc_trustdom_list(int argc, const char **argv)
06036 {
06037         /* common variables */
06038         TALLOC_CTX* mem_ctx;
06039         struct cli_state *cli = NULL, *remote_cli = NULL;
06040         struct rpc_pipe_client *pipe_hnd = NULL;
06041         NTSTATUS nt_status;
06042         const char *domain_name = NULL;
06043         DOM_SID *queried_dom_sid;
06044         fstring padding;
06045         int ascii_dom_name_len;
06046         POLICY_HND connect_hnd;
06047         
06048         /* trusted domains listing variables */
06049         unsigned int num_domains, enum_ctx = 0;
06050         int i, pad_len, col_len = 20;
06051         DOM_SID *domain_sids;
06052         char **trusted_dom_names;
06053         fstring pdc_name;
06054         char *dummy;
06055         
06056         /* trusting domains listing variables */
06057         POLICY_HND domain_hnd;
06058         char **trusting_dom_names;
06059         uint32 *trusting_dom_rids;
06060         
06061         /*
06062          * Listing trusted domains (stored in secrets.tdb, if local)
06063          */
06064 
06065         mem_ctx = talloc_init("trust relationships listing");
06066 
06067         /*
06068          * set domain and pdc name to local samba server (default)
06069          * or to remote one given in command line
06070          */
06071         
06072         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
06073                 domain_name = opt_workgroup;
06074                 opt_target_workgroup = opt_workgroup;
06075         } else {
06076                 fstrcpy(pdc_name, global_myname());
06077                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
06078                 opt_target_workgroup = domain_name;
06079         };
06080 
06081         /* open \PIPE\lsarpc and open policy handle */
06082         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
06083                 DEBUG(0, ("Couldn't connect to domain controller\n"));
06084                 talloc_destroy(mem_ctx);
06085                 return -1;
06086         };
06087 
06088         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
06089         if (!pipe_hnd) {
06090                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
06091                         nt_errstr(nt_status) ));
06092                 cli_shutdown(cli);
06093                 talloc_destroy(mem_ctx);
06094                 return -1;
06095         };
06096 
06097         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
06098                                         &connect_hnd);
06099         if (NT_STATUS_IS_ERR(nt_status)) {
06100                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
06101                         nt_errstr(nt_status)));
06102                 cli_shutdown(cli);
06103                 talloc_destroy(mem_ctx);
06104                 return -1;
06105         };
06106         
06107         /* query info level 5 to obtain sid of a domain being queried */
06108         nt_status = rpccli_lsa_query_info_policy(
06109                 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
06110                 &dummy, &queried_dom_sid);
06111 
06112         if (NT_STATUS_IS_ERR(nt_status)) {
06113                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
06114                         nt_errstr(nt_status)));
06115                 cli_shutdown(cli);
06116                 talloc_destroy(mem_ctx);
06117                 return -1;
06118         }
06119                 
06120         /*
06121          * Keep calling LsaEnumTrustdom over opened pipe until
06122          * the end of enumeration is reached
06123          */
06124          
06125         d_printf("Trusted domains list:\n\n");
06126 
06127         do {
06128                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
06129                                                    &num_domains,
06130                                                    &trusted_dom_names, &domain_sids);
06131                 
06132                 if (NT_STATUS_IS_ERR(nt_status)) {
06133                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
06134                                 nt_errstr(nt_status)));
06135                         cli_shutdown(cli);
06136                         talloc_destroy(mem_ctx);
06137                         return -1;
06138                 };
06139                 
06140                 for (i = 0; i < num_domains; i++) {
06141                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
06142                 };
06143                 
06144                 /*
06145                  * in case of no trusted domains say something rather
06146                  * than just display blank line
06147                  */
06148                 if (!num_domains) d_printf("none\n");
06149 
06150         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
06151 
06152         /* close this connection before doing next one */
06153         nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
06154         if (NT_STATUS_IS_ERR(nt_status)) {
06155                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
06156                         nt_errstr(nt_status)));
06157                 cli_shutdown(cli);
06158                 talloc_destroy(mem_ctx);
06159                 return -1;
06160         };
06161         
06162         cli_rpc_pipe_close(pipe_hnd);
06163 
06164         /*
06165          * Listing trusting domains (stored in passdb backend, if local)
06166          */
06167         
06168         d_printf("\nTrusting domains list:\n\n");
06169 
06170         /*
06171          * Open \PIPE\samr and get needed policy handles
06172          */
06173         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
06174         if (!pipe_hnd) {
06175                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
06176                 cli_shutdown(cli);
06177                 talloc_destroy(mem_ctx);
06178                 return -1;
06179         };
06180         
06181         /* SamrConnect */
06182         nt_status = rpccli_samr_connect(pipe_hnd, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
06183                                                                  &connect_hnd);
06184         if (!NT_STATUS_IS_OK(nt_status)) {
06185                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
06186                         nt_errstr(nt_status)));
06187                 cli_shutdown(cli);
06188                 talloc_destroy(mem_ctx);
06189                 return -1;
06190         };
06191         
06192         /* SamrOpenDomain - we have to open domain policy handle in order to be
06193            able to enumerate accounts*/
06194         nt_status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_hnd,
06195                                          SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
06196                                          queried_dom_sid, &domain_hnd);                                                                  
06197         if (!NT_STATUS_IS_OK(nt_status)) {
06198                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
06199                         nt_errstr(nt_status)));
06200                 cli_shutdown(cli);
06201                 talloc_destroy(mem_ctx);
06202                 return -1;
06203         };
06204         
06205         /*
06206          * perform actual enumeration
06207          */
06208          
06209         enum_ctx = 0;   /* reset enumeration context from last enumeration */
06210         do {
06211                         
06212                 nt_status = rpccli_samr_enum_dom_users(pipe_hnd, mem_ctx, &domain_hnd,
06213                                                     &enum_ctx, ACB_DOMTRUST, 0xffff,
06214                                                     &trusting_dom_names, &trusting_dom_rids,
06215                                                     &num_domains);
06216                 if (NT_STATUS_IS_ERR(nt_status)) {
06217                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
06218                                 nt_errstr(nt_status)));
06219                         cli_shutdown(cli);
06220                         talloc_destroy(mem_ctx);
06221                         return -1;
06222                 };
06223                 
06224                 for (i = 0; i < num_domains; i++) {
06225 
06226                         /*
06227                          * get each single domain's sid (do we _really_ need this ?):
06228                          *  1) connect to domain's pdc
06229                          *  2) query the pdc for domain's sid
06230                          */
06231 
06232                         /* get rid of '$' tail */
06233                         ascii_dom_name_len = strlen(trusting_dom_names[i]);
06234                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
06235                                 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
06236                         
06237                         /* calculate padding space for d_printf to look nicer */
06238                         pad_len = col_len - strlen(trusting_dom_names[i]);
06239                         padding[pad_len] = 0;
06240                         do padding[--pad_len] = ' '; while (pad_len);
06241 
06242                         /* set opt_* variables to remote domain */
06243                         strupper_m(trusting_dom_names[i]);
06244                         opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
06245                         opt_target_workgroup = opt_workgroup;
06246                         
06247                         d_printf("%s%s", trusting_dom_names[i], padding);
06248                         
06249                         /* connect to remote domain controller */
06250                         remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
06251                         if (remote_cli) {                       
06252                                 /* query for domain's sid */
06253                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
06254                                         d_fprintf(stderr, "couldn't get domain's sid\n");
06255 
06256                                 cli_shutdown(remote_cli);
06257                         
06258                         } else {
06259                                 d_fprintf(stderr, "domain controller is not responding\n");
06260                         };
06261                 };
06262                 
06263                 if (!num_domains) d_printf("none\n");
06264                 
06265         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
06266 
06267         /* close opened samr and domain policy handles */
06268         nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &domain_hnd);
06269         if (!NT_STATUS_IS_OK(nt_status)) {
06270                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
06271         };
06272         
06273         nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &connect_hnd);
06274         if (!NT_STATUS_IS_OK(nt_status)) {
06275                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
06276         };
06277         
06278         /* close samr pipe and connection to IPC$ */
06279         cli_shutdown(cli);
06280 
06281         talloc_destroy(mem_ctx);         
06282         return 0;
06283 }
06284 
06285 /**
06286  * Entrypoint for 'net rpc trustdom' code
06287  *
06288  * @param argc standard argc
06289  * @param argv standard argv without initial components
06290  *
06291  * @return Integer status (0 means success)
06292  */
06293 
06294 static int rpc_trustdom(int argc, const char **argv)
06295 {
06296         struct functable func[] = {
06297                 {"add", rpc_trustdom_add},
06298                 {"del", rpc_trustdom_del},
06299                 {"establish", rpc_trustdom_establish},
06300                 {"revoke", rpc_trustdom_revoke},
06301                 {"help", rpc_trustdom_usage},
06302                 {"list", rpc_trustdom_list},
06303                 {"vampire", rpc_trustdom_vampire},
06304                 {NULL, NULL}
06305         };
06306 
06307         if (argc == 0) {
06308                 rpc_trustdom_usage(argc, argv);
06309                 return -1;
06310         }
06311 
06312         return (net_run_function(argc, argv, func, rpc_user_usage));
06313 }
06314 
06315 /**
06316  * Check if a server will take rpc commands
06317  * @param flags Type of server to connect to (PDC, DMB, localhost)
06318  *              if the host is not explicitly specified
06319  * @return  BOOL (true means rpc supported)
06320  */
06321 BOOL net_rpc_check(unsigned flags)
06322 {
06323         struct cli_state *cli;
06324         BOOL ret = False;
06325         struct in_addr server_ip;
06326         char *server_name = NULL;
06327         NTSTATUS status;
06328 
06329         /* flags (i.e. server type) may depend on command */
06330         if (!net_find_server(NULL, flags, &server_ip, &server_name))
06331                 return False;
06332 
06333         if ((cli = cli_initialise()) == NULL) {
06334                 return False;
06335         }
06336 
06337         status = cli_connect(cli, server_name, &server_ip);
06338         if (!NT_STATUS_IS_OK(status))
06339                 goto done;
06340         if (!attempt_netbios_session_request(&cli, global_myname(), 
06341                                              server_name, &server_ip))
06342                 goto done;
06343         if (!cli_negprot(cli))
06344                 goto done;
06345         if (cli->protocol < PROTOCOL_NT1)
06346                 goto done;
06347 
06348         ret = True;
06349  done:
06350         cli_shutdown(cli);
06351         return ret;
06352 }
06353 
06354 /* dump sam database via samsync rpc calls */
06355 static int rpc_samdump(int argc, const char **argv) {
06356                 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
06357                                argc, argv);
06358 }
06359 
06360 /* syncronise sam database via samsync rpc calls */
06361 static int rpc_vampire(int argc, const char **argv) {
06362         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
06363                                argc, argv);
06364 }
06365 
06366 /** 
06367  * Migrate everything from a print-server
06368  *
06369  * @param argc  Standard main() style argc
06370  * @param argv  Standard main() style argv.  Initial components are already
06371  *              stripped
06372  *
06373  * @return A shell status integer (0 for success)
06374  *
06375  * The order is important !
06376  * To successfully add drivers the print-queues have to exist !
06377  * Applying ACLs should be the last step, because you're easily locked out
06378  *
06379  **/
06380 static int rpc_printer_migrate_all(int argc, const char **argv)
06381 {
06382         int ret;
06383 
06384         if (!opt_host) {
06385                 printf("no server to migrate\n");
06386                 return -1;
06387         }
06388 
06389         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
06390         if (ret)
06391                 return ret;
06392 
06393         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
06394         if (ret)
06395                 return ret;
06396 
06397         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
06398         if (ret)
06399                 return ret;
06400 
06401         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
06402         if (ret)
06403                 return ret;
06404 
06405         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
06406 
06407 }
06408 
06409 /** 
06410  * Migrate print-drivers from a print-server
06411  *
06412  * @param argc  Standard main() style argc
06413  * @param argv  Standard main() style argv.  Initial components are already
06414  *              stripped
06415  *
06416  * @return A shell status integer (0 for success)
06417  **/
06418 static int rpc_printer_migrate_drivers(int argc, const char **argv)
06419 {
06420         if (!opt_host) {
06421                 printf("no server to migrate\n");
06422                 return -1;
06423         }
06424 
06425         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06426                                rpc_printer_migrate_drivers_internals,
06427                                argc, argv);
06428 }
06429 
06430 /** 
06431  * Migrate print-forms from a print-server
06432  *
06433  * @param argc  Standard main() style argc
06434  * @param argv  Standard main() style argv.  Initial components are already
06435  *              stripped
06436  *
06437  * @return A shell status integer (0 for success)
06438  **/
06439 static int rpc_printer_migrate_forms(int argc, const char **argv)
06440 {
06441         if (!opt_host) {
06442                 printf("no server to migrate\n");
06443                 return -1;
06444         }
06445 
06446         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06447                                rpc_printer_migrate_forms_internals,
06448                                argc, argv);
06449 }
06450 
06451 /** 
06452  * Migrate printers from a print-server
06453  *
06454  * @param argc  Standard main() style argc
06455  * @param argv  Standard main() style argv.  Initial components are already
06456  *              stripped
06457  *
06458  * @return A shell status integer (0 for success)
06459  **/
06460 static int rpc_printer_migrate_printers(int argc, const char **argv)
06461 {
06462         if (!opt_host) {
06463                 printf("no server to migrate\n");
06464                 return -1;
06465         }
06466 
06467         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06468                                rpc_printer_migrate_printers_internals,
06469                                argc, argv);
06470 }
06471 
06472 /** 
06473  * Migrate printer-ACLs from a print-server
06474  *
06475  * @param argc  Standard main() style argc
06476  * @param argv  Standard main() style argv.  Initial components are already
06477  *              stripped
06478  *
06479  * @return A shell status integer (0 for success)
06480  **/
06481 static int rpc_printer_migrate_security(int argc, const char **argv)
06482 {
06483         if (!opt_host) {
06484                 printf("no server to migrate\n");
06485                 return -1;
06486         }
06487 
06488         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06489                                rpc_printer_migrate_security_internals,
06490                                argc, argv);
06491 }
06492 
06493 /** 
06494  * Migrate printer-settings from a print-server
06495  *
06496  * @param argc  Standard main() style argc
06497  * @param argv  Standard main() style argv.  Initial components are already
06498  *              stripped
06499  *
06500  * @return A shell status integer (0 for success)
06501  **/
06502 static int rpc_printer_migrate_settings(int argc, const char **argv)
06503 {
06504         if (!opt_host) {
06505                 printf("no server to migrate\n");
06506                 return -1;
06507         }
06508 
06509         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06510                                rpc_printer_migrate_settings_internals,
06511                                argc, argv);
06512 }
06513 
06514 /** 
06515  * 'net rpc printer' entrypoint.
06516  * @param argc  Standard main() style argc
06517  * @param argv  Standard main() style argv.  Initial components are already
06518  *              stripped
06519  **/
06520 
06521 int rpc_printer_migrate(int argc, const char **argv) 
06522 {
06523 
06524         /* ouch: when addriver and setdriver are called from within
06525            rpc_printer_migrate_drivers_internals, the printer-queue already
06526            *has* to exist */
06527 
06528         struct functable func[] = {
06529                 {"all",         rpc_printer_migrate_all},
06530                 {"drivers",     rpc_printer_migrate_drivers},
06531                 {"forms",       rpc_printer_migrate_forms},
06532                 {"help",        rpc_printer_usage},
06533                 {"printers",    rpc_printer_migrate_printers},
06534                 {"security",    rpc_printer_migrate_security},
06535                 {"settings",    rpc_printer_migrate_settings},
06536                 {NULL, NULL}
06537         };
06538 
06539         return net_run_function(argc, argv, func, rpc_printer_usage);
06540 }
06541 
06542 
06543 /** 
06544  * List printers on a remote RPC server
06545  *
06546  * @param argc  Standard main() style argc
06547  * @param argv  Standard main() style argv.  Initial components are already
06548  *              stripped
06549  *
06550  * @return A shell status integer (0 for success)
06551  **/
06552 static int rpc_printer_list(int argc, const char **argv)
06553 {
06554 
06555         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06556                                rpc_printer_list_internals,
06557                                argc, argv);
06558 }
06559 
06560 /** 
06561  * List printer-drivers on a remote RPC server
06562  *
06563  * @param argc  Standard main() style argc
06564  * @param argv  Standard main() style argv.  Initial components are already
06565  *              stripped
06566  *
06567  * @return A shell status integer (0 for success)
06568  **/
06569 static int rpc_printer_driver_list(int argc, const char **argv)
06570 {
06571 
06572         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06573                                rpc_printer_driver_list_internals,
06574                                argc, argv);
06575 }
06576 
06577 /** 
06578  * Publish printer in ADS via MSRPC
06579  *
06580  * @param argc  Standard main() style argc
06581  * @param argv  Standard main() style argv.  Initial components are already
06582  *              stripped
06583  *
06584  * @return A shell status integer (0 for success)
06585  **/
06586 static int rpc_printer_publish_publish(int argc, const char **argv)
06587 {
06588 
06589         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06590                                rpc_printer_publish_publish_internals,
06591                                argc, argv);
06592 }
06593 
06594 /** 
06595  * Update printer in ADS via MSRPC
06596  *
06597  * @param argc  Standard main() style argc
06598  * @param argv  Standard main() style argv.  Initial components are already
06599  *              stripped
06600  *
06601  * @return A shell status integer (0 for success)
06602  **/
06603 static int rpc_printer_publish_update(int argc, const char **argv)
06604 {
06605 
06606         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06607                                rpc_printer_publish_update_internals,
06608                                argc, argv);
06609 }
06610 
06611 /** 
06612  * UnPublish printer in ADS via MSRPC
06613  *
06614  * @param argc  Standard main() style argc
06615  * @param argv  Standard main() style argv.  Initial components are already
06616  *              stripped
06617  *
06618  * @return A shell status integer (0 for success)
06619  **/
06620 static int rpc_printer_publish_unpublish(int argc, const char **argv)
06621 {
06622 
06623         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06624                                rpc_printer_publish_unpublish_internals,
06625                                argc, argv);
06626 }
06627 
06628 /** 
06629  * List published printers via MSRPC
06630  *
06631  * @param argc  Standard main() style argc
06632  * @param argv  Standard main() style argv.  Initial components are already
06633  *              stripped
06634  *
06635  * @return A shell status integer (0 for success)
06636  **/
06637 static int rpc_printer_publish_list(int argc, const char **argv)
06638 {
06639 
06640         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06641                                rpc_printer_publish_list_internals,
06642                                argc, argv);
06643 }
06644 
06645 
06646 /** 
06647  * Publish printer in ADS
06648  *
06649  * @param argc  Standard main() style argc
06650  * @param argv  Standard main() style argv.  Initial components are already
06651  *              stripped
06652  *
06653  * @return A shell status integer (0 for success)
06654  **/
06655 static int rpc_printer_publish(int argc, const char **argv)
06656 {
06657 
06658         struct functable func[] = {
06659                 {"publish",     rpc_printer_publish_publish},
06660                 {"update",      rpc_printer_publish_update},
06661                 {"unpublish",   rpc_printer_publish_unpublish},
06662                 {"list",        rpc_printer_publish_list},
06663                 {"help",        rpc_printer_usage},
06664                 {NULL, NULL}
06665         };
06666 
06667         if (argc == 0)
06668                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06669                                rpc_printer_publish_list_internals,
06670                                argc, argv);
06671 
06672         return net_run_function(argc, argv, func, rpc_printer_usage);
06673 
06674 }
06675 
06676 
06677 /** 
06678  * Display rpc printer help page.
06679  * @param argc  Standard main() style argc
06680  * @param argv  Standard main() style argv.  Initial components are already
06681  *              stripped
06682  **/
06683 int rpc_printer_usage(int argc, const char **argv)
06684 {
06685         return net_help_printer(argc, argv);
06686 }
06687 
06688 /** 
06689  * 'net rpc printer' entrypoint.
06690  * @param argc  Standard main() style argc
06691  * @param argv  Standard main() style argv.  Initial components are already
06692  *              stripped
06693  **/
06694 int net_rpc_printer(int argc, const char **argv) 
06695 {
06696         struct functable func[] = {
06697                 {"list", rpc_printer_list},
06698                 {"migrate", rpc_printer_migrate},
06699                 {"driver", rpc_printer_driver_list},
06700                 {"publish", rpc_printer_publish},
06701                 {NULL, NULL}
06702         };
06703 
06704         if (argc == 0)
06705                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
06706                                rpc_printer_list_internals,
06707                                argc, argv);
06708 
06709         return net_run_function(argc, argv, func, rpc_printer_usage);
06710 }
06711 
06712 /****************************************************************************/
06713 
06714 
06715 /** 
06716  * Basic usage function for 'net rpc'
06717  * @param argc  Standard main() style argc
06718  * @param argv  Standard main() style argv.  Initial components are already
06719  *              stripped
06720  **/
06721 
06722 int net_rpc_usage(int argc, const char **argv) 
06723 {
06724         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
06725         d_printf("  net rpc join \t\t\tto join a domain \n");
06726         d_printf("  net rpc oldjoin \t\t\tto join a domain created in server manager\n");
06727         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
06728         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
06729         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
06730         d_printf("  net rpc group \t\tto list groups\n");
06731         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
06732         d_printf("  net rpc printer \t\tto list and migrate printers\n");
06733         d_printf("  net rpc file \t\t\tto list open files\n");
06734         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
06735         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
06736         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
06737         d_printf("  net rpc samdump \t\tdiplay an NT PDC's users, groups and other data\n");
06738         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
06739         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
06740         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
06741         d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
06742         d_printf("  net rpc registry\t\tto manage registry hives\n");
06743         d_printf("  net rpc service\t\tto start, stop and query services\n");
06744         d_printf("  net rpc audit\t\t\tto modify global auditing settings\n");
06745         d_printf("  net rpc shell\t\t\tto open an interactive shell for remote server/account management\n");
06746         d_printf("\n");
06747         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
06748         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
06749         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
06750         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
06751         d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
06752         return -1;
06753 }
06754 
06755 
06756 /**
06757  * Help function for 'net rpc'.  Calls command specific help if requested
06758  * or displays usage of net rpc
06759  * @param argc  Standard main() style argc
06760  * @param argv  Standard main() style argv.  Initial components are already
06761  *              stripped
06762  **/
06763 
06764 int net_rpc_help(int argc, const char **argv)
06765 {
06766         struct functable func[] = {
06767                 {"join", rpc_join_usage},
06768                 {"user", rpc_user_usage},
06769                 {"group", rpc_group_usage},
06770                 {"share", rpc_share_usage},
06771                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
06772                 {"trustdom", rpc_trustdom_usage},
06773                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
06774                 /*{"shutdown", rpc_shutdown_usage}, */
06775                 {"vampire", rpc_vampire_usage},
06776                 {NULL, NULL}
06777         };
06778 
06779         if (argc == 0) {
06780                 net_rpc_usage(argc, argv);
06781                 return -1;
06782         }
06783 
06784         return (net_run_function(argc, argv, func, rpc_user_usage));
06785 }
06786 
06787 /** 
06788  * 'net rpc' entrypoint.
06789  * @param argc  Standard main() style argc
06790  * @param argv  Standard main() style argv.  Initial components are already
06791  *              stripped
06792  **/
06793 
06794 int net_rpc(int argc, const char **argv)
06795 {
06796         struct functable func[] = {
06797                 {"audit", net_rpc_audit},
06798                 {"info", net_rpc_info},
06799                 {"join", net_rpc_join},
06800                 {"oldjoin", net_rpc_oldjoin},
06801                 {"testjoin", net_rpc_testjoin},
06802                 {"user", net_rpc_user},
06803                 {"password", rpc_user_password},
06804                 {"group", net_rpc_group},
06805                 {"share", net_rpc_share},
06806                 {"file", net_rpc_file},
06807                 {"printer", net_rpc_printer},
06808                 {"changetrustpw", net_rpc_changetrustpw},
06809                 {"trustdom", rpc_trustdom},
06810                 {"abortshutdown", rpc_shutdown_abort},
06811                 {"shutdown", rpc_shutdown},
06812                 {"samdump", rpc_samdump},
06813                 {"vampire", rpc_vampire},
06814                 {"getsid", net_rpc_getsid},
06815                 {"rights", net_rpc_rights},
06816                 {"service", net_rpc_service},
06817                 {"registry", net_rpc_registry},
06818                 {"shell", net_rpc_shell},
06819                 {"help", net_rpc_help},
06820                 {NULL, NULL}
06821         };
06822         return net_run_function(argc, argv, func, net_rpc_usage);
06823 }

Sambaに対してSat Aug 29 21:23:29 2009に生成されました。  doxygen 1.4.7