LCOV - code coverage report
Current view: top level - source3/rpcclient - rpcclient.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 274 514 53.3 %
Date: 2024-04-21 15:09:00 Functions: 13 25 52.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    RPC pipe client
       4             : 
       5             :    Copyright (C) Tim Potter 2000-2001
       6             :    Copyright (C) Martin Pool 2003
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "../libcli/auth/netlogon_creds_cli.h"
      24             : #include "rpcclient.h"
      25             : #include "../libcli/auth/libcli_auth.h"
      26             : #include "../librpc/gen_ndr/ndr_lsa_c.h"
      27             : #include "rpc_client/cli_lsarpc.h"
      28             : #include "../librpc/gen_ndr/ndr_netlogon.h"
      29             : #include "rpc_client/cli_netlogon.h"
      30             : #include "../libcli/smbreadline/smbreadline.h"
      31             : #include "../libcli/security/security.h"
      32             : #include "passdb.h"
      33             : #include "libsmb/libsmb.h"
      34             : #include "auth/gensec/gensec.h"
      35             : #include "../libcli/smb/smbXcli_base.h"
      36             : #include "messages.h"
      37             : #include "cmdline_contexts.h"
      38             : #include "../librpc/gen_ndr/ndr_samr.h"
      39             : #include "lib/cmdline/cmdline.h"
      40             : #include "lib/param/param.h"
      41             : 
      42             : enum pipe_auth_type_spnego {
      43             :         PIPE_AUTH_TYPE_SPNEGO_NONE = 0,
      44             :         PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
      45             :         PIPE_AUTH_TYPE_SPNEGO_KRB5
      46             : };
      47             : 
      48             : static unsigned int timeout = 10000;
      49             : 
      50             : struct messaging_context *rpcclient_msg_ctx;
      51             : struct netlogon_creds_cli_context *rpcclient_netlogon_creds;
      52             : static const char *rpcclient_netlogon_domain;
      53             : 
      54             : /* List to hold groups of commands.
      55             :  *
      56             :  * Commands are defined in a list of arrays: arrays are easy to
      57             :  * statically declare, and lists are easier to dynamically extend.
      58             :  */
      59             : 
      60             : static struct cmd_list {
      61             :         struct cmd_list *prev, *next;
      62             :         struct cmd_set *cmd_set;
      63             : } *cmd_list;
      64             : 
      65             : /****************************************************************************
      66             : handle completion of commands for readline
      67             : ****************************************************************************/
      68           0 : static char **completion_fn(const char *text, int start, int end)
      69             : {
      70             : #define MAX_COMPLETIONS 1000
      71             :         char **matches;
      72           0 :         size_t i, count=0;
      73           0 :         struct cmd_list *commands = cmd_list;
      74             : 
      75             : #if 0   /* JERRY */
      76             :         /* FIXME!!!  -- what to do when completing argument? */
      77             :         /* for words not at the start of the line fallback
      78             :            to filename completion */
      79             :         if (start)
      80             :                 return NULL;
      81             : #endif
      82             : 
      83             :         /* make sure we have a list of valid commands */
      84           0 :         if (!commands) {
      85           0 :                 return NULL;
      86             :         }
      87             : 
      88           0 :         matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
      89           0 :         if (!matches) {
      90           0 :                 return NULL;
      91             :         }
      92             : 
      93           0 :         matches[count++] = SMB_STRDUP(text);
      94           0 :         if (!matches[0]) {
      95           0 :                 SAFE_FREE(matches);
      96           0 :                 return NULL;
      97             :         }
      98             : 
      99           0 :         while (commands && count < MAX_COMPLETIONS-1) {
     100           0 :                 if (!commands->cmd_set) {
     101           0 :                         break;
     102             :                 }
     103             : 
     104           0 :                 for (i=0; commands->cmd_set[i].name; i++) {
     105           0 :                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
     106           0 :                                 (( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS &&
     107           0 :                         commands->cmd_set[i].ntfn ) ||
     108           0 :                       ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
     109           0 :                         commands->cmd_set[i].wfn))) {
     110           0 :                                 matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
     111           0 :                                 if (!matches[count]) {
     112           0 :                                         for (i = 0; i < count; i++) {
     113           0 :                                                 SAFE_FREE(matches[count]);
     114             :                                         }
     115           0 :                                         SAFE_FREE(matches);
     116           0 :                                         return NULL;
     117             :                                 }
     118           0 :                                 count++;
     119             :                         }
     120             :                 }
     121           0 :                 commands = commands->next;
     122             :         }
     123             : 
     124           0 :         if (count == 2) {
     125           0 :                 SAFE_FREE(matches[0]);
     126           0 :                 matches[0] = SMB_STRDUP(matches[1]);
     127             :         }
     128           0 :         matches[count] = NULL;
     129           0 :         return matches;
     130             : }
     131             : 
     132        1408 : static char *next_command (char **cmdstr)
     133             : {
     134             :         char *command;
     135             :         char                    *p;
     136             : 
     137        1408 :         if (!cmdstr || !(*cmdstr))
     138         692 :                 return NULL;
     139             : 
     140         716 :         p = strchr_m(*cmdstr, ';');
     141         716 :         if (p)
     142          24 :                 *p = '\0';
     143         716 :         command = SMB_STRDUP(*cmdstr);
     144         716 :         if (p)
     145          24 :                 *cmdstr = p + 1;
     146             :         else
     147         692 :                 *cmdstr = NULL;
     148             : 
     149         716 :         return command;
     150             : }
     151             : 
     152         554 : static void binding_get_auth_info(
     153             :         const struct dcerpc_binding *b,
     154             :         enum dcerpc_AuthType *_auth_type,
     155             :         enum dcerpc_AuthLevel *_auth_level,
     156             :         enum credentials_use_kerberos *_krb5_state)
     157             : {
     158         554 :         uint32_t bflags = dcerpc_binding_get_flags(b);
     159         554 :         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
     160         554 :         enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
     161         554 :         enum credentials_use_kerberos krb5_state = CRED_USE_KERBEROS_DESIRED;
     162             : 
     163         554 :         if (_krb5_state != NULL) {
     164         540 :                 krb5_state = *_krb5_state;
     165             :         }
     166             : 
     167         554 :         if (bflags & DCERPC_CONNECT) {
     168          30 :                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
     169             :         }
     170         554 :         if (bflags & DCERPC_PACKET) {
     171          54 :                 auth_level = DCERPC_AUTH_LEVEL_PACKET;
     172             :         }
     173         554 :         if (bflags & DCERPC_SIGN) {
     174          68 :                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
     175             :         }
     176         554 :         if (bflags & DCERPC_SEAL) {
     177          68 :                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
     178             :         }
     179             : 
     180         554 :         if (bflags & DCERPC_SCHANNEL) {
     181          32 :                 auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
     182             :         }
     183             : 
     184         554 :         if ((auth_level != DCERPC_AUTH_LEVEL_NONE) &&
     185             :             (auth_type == DCERPC_AUTH_TYPE_NONE)) {
     186         192 :                 auth_type = (krb5_state == CRED_USE_KERBEROS_REQUIRED) ?
     187         192 :                         DCERPC_AUTH_TYPE_KRB5 : DCERPC_AUTH_TYPE_NTLMSSP;
     188             :         }
     189             : 
     190         554 :         if (bflags & DCERPC_AUTH_SPNEGO) {
     191         159 :                 auth_type = DCERPC_AUTH_TYPE_SPNEGO;
     192             : 
     193         159 :                 if (bflags & DCERPC_AUTH_NTLM) {
     194          36 :                         krb5_state = CRED_USE_KERBEROS_DISABLED;
     195             :                 }
     196         159 :                 if (bflags & DCERPC_AUTH_KRB5) {
     197          15 :                         krb5_state = CRED_USE_KERBEROS_REQUIRED;
     198             :                 }
     199             :         }
     200             : 
     201         554 :         if (auth_type != DCERPC_AUTH_TYPE_NONE) {
     202             :                 /* If nothing is requested then default to integrity */
     203         259 :                 if (auth_level == DCERPC_AUTH_LEVEL_NONE) {
     204          39 :                         auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
     205             :                 }
     206             :         }
     207             : 
     208         554 :         if (_auth_type != NULL) {
     209         554 :                 *_auth_type = auth_type;
     210             :         }
     211         554 :         if (_auth_level != NULL) {
     212         554 :                 *_auth_level = auth_level;
     213             :         }
     214         554 :         if (_krb5_state != NULL) {
     215         540 :                 *_krb5_state = krb5_state;
     216             :         }
     217         554 : }
     218             : 
     219             : /* List the available commands on a given pipe */
     220             : 
     221           0 : static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
     222             :                                  int argc, const char **argv)
     223             : {
     224             :         struct cmd_list *tmp;
     225             :         struct cmd_set *tmp_set;
     226             :         int i;
     227             : 
     228             :         /* Usage */
     229             : 
     230           0 :         if (argc != 2) {
     231           0 :                 printf("Usage: %s <pipe>\n", argv[0]);
     232           0 :                 return NT_STATUS_OK;
     233             :         }
     234             : 
     235             :         /* Help on one command */
     236             : 
     237           0 :         for (tmp = cmd_list; tmp; tmp = tmp->next)
     238             :         {
     239           0 :                 tmp_set = tmp->cmd_set;
     240             : 
     241           0 :                 if (!strcasecmp_m(argv[1], tmp_set->name))
     242             :                 {
     243           0 :                         printf("Available commands on the %s pipe:\n\n", tmp_set->name);
     244             : 
     245           0 :                         i = 0;
     246           0 :                         tmp_set++;
     247           0 :                         while(tmp_set->name) {
     248           0 :                                 printf("%30s", tmp_set->name);
     249           0 :                                 tmp_set++;
     250           0 :                                 i++;
     251           0 :                                 if (i%3 == 0)
     252           0 :                                         printf("\n");
     253             :                         }
     254             : 
     255             :                         /* drop out of the loop */
     256           0 :                         break;
     257             :                 }
     258             :         }
     259           0 :         printf("\n\n");
     260             : 
     261           0 :         return NT_STATUS_OK;
     262             : }
     263             : 
     264             : /* Display help on commands */
     265             : 
     266           0 : static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
     267             :                          int argc, const char **argv)
     268             : {
     269             :         struct cmd_list *tmp;
     270             :         struct cmd_set *tmp_set;
     271             : 
     272             :         /* Usage */
     273             : 
     274           0 :         if (argc > 2) {
     275           0 :                 printf("Usage: %s [command]\n", argv[0]);
     276           0 :                 return NT_STATUS_OK;
     277             :         }
     278             : 
     279             :         /* Help on one command */
     280             : 
     281           0 :         if (argc == 2) {
     282           0 :                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
     283             : 
     284           0 :                         tmp_set = tmp->cmd_set;
     285             : 
     286           0 :                         while(tmp_set->name) {
     287           0 :                                 if (strequal(argv[1], tmp_set->name)) {
     288           0 :                                         if (tmp_set->usage &&
     289           0 :                                             tmp_set->usage[0])
     290           0 :                                                 printf("%s\n", tmp_set->usage);
     291             :                                         else
     292           0 :                                                 printf("No help for %s\n", tmp_set->name);
     293             : 
     294           0 :                                         return NT_STATUS_OK;
     295             :                                 }
     296             : 
     297           0 :                                 tmp_set++;
     298             :                         }
     299             :                 }
     300             : 
     301           0 :                 printf("No such command: %s\n", argv[1]);
     302           0 :                 return NT_STATUS_OK;
     303             :         }
     304             : 
     305             :         /* List all commands */
     306             : 
     307           0 :         for (tmp = cmd_list; tmp; tmp = tmp->next) {
     308             : 
     309           0 :                 tmp_set = tmp->cmd_set;
     310             : 
     311           0 :                 while(tmp_set->name) {
     312             : 
     313           0 :                         printf("%15s\t\t%s\n", tmp_set->name,
     314           0 :                                tmp_set->description ? tmp_set->description:
     315             :                                "");
     316             : 
     317           0 :                         tmp_set++;
     318             :                 }
     319             :         }
     320             : 
     321           0 :         return NT_STATUS_OK;
     322             : }
     323             : 
     324             : /* Change the debug level */
     325             : 
     326           0 : static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
     327             :                                int argc, const char **argv)
     328             : {
     329           0 :         if (argc > 2) {
     330           0 :                 printf("Usage: %s [debuglevel]\n", argv[0]);
     331           0 :                 return NT_STATUS_OK;
     332             :         }
     333             : 
     334           0 :         if (argc == 2) {
     335           0 :                 struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
     336           0 :                 lpcfg_set_cmdline(lp_ctx, "log level", argv[1]);
     337             :         }
     338             : 
     339           0 :         printf("debuglevel is %d\n", DEBUGLEVEL);
     340             : 
     341           0 :         return NT_STATUS_OK;
     342             : }
     343             : 
     344           0 : static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
     345             :                          int argc, const char **argv)
     346             : {
     347           0 :         exit(0);
     348             :         return NT_STATUS_OK; /* NOTREACHED */
     349             : }
     350             : 
     351          14 : static NTSTATUS cmd_set_ss_level(struct dcerpc_binding *binding)
     352             : {
     353             :         struct cmd_list *tmp;
     354             :         enum dcerpc_AuthType auth_type;
     355             :         enum dcerpc_AuthLevel auth_level;
     356             : 
     357             :         /* Close any existing connections not at this level. */
     358             : 
     359          14 :         binding_get_auth_info(binding, &auth_type, &auth_level, NULL);
     360             : 
     361         630 :         for (tmp = cmd_list; tmp; tmp = tmp->next) {
     362             :                 struct cmd_set *tmp_set;
     363             : 
     364        4508 :                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
     365        3892 :                         if (tmp_set->rpc_pipe == NULL) {
     366        3892 :                                 continue;
     367             :                         }
     368             : 
     369           0 :                         if ((tmp_set->rpc_pipe->auth->auth_type
     370           0 :                              != auth_type)
     371           0 :                             || (tmp_set->rpc_pipe->auth->auth_level
     372           0 :                                 != auth_level)) {
     373           0 :                                 TALLOC_FREE(tmp_set->rpc_pipe);
     374           0 :                                 tmp_set->rpc_pipe = NULL;
     375             :                         }
     376             :                 }
     377             :         }
     378          14 :         return NT_STATUS_OK;
     379             : }
     380             : 
     381           0 : static NTSTATUS cmd_set_transport(struct dcerpc_binding *b)
     382             : {
     383           0 :         enum dcerpc_transport_t t = dcerpc_binding_get_transport(b);
     384             :         struct cmd_list *tmp;
     385             : 
     386             :         /* Close any existing connections not at this level. */
     387             : 
     388           0 :         for (tmp = cmd_list; tmp; tmp = tmp->next) {
     389             :                 struct cmd_set *tmp_set;
     390             : 
     391           0 :                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
     392           0 :                         if (tmp_set->rpc_pipe == NULL) {
     393           0 :                                 continue;
     394             :                         }
     395             : 
     396           0 :                         if (tmp_set->rpc_pipe->transport->transport != t) {
     397           0 :                                 TALLOC_FREE(tmp_set->rpc_pipe);
     398           0 :                                 tmp_set->rpc_pipe = NULL;
     399             :                         }
     400             :                 }
     401             :         }
     402           0 :         return NT_STATUS_OK;
     403             : }
     404             : 
     405          14 : static NTSTATUS binding_reset_auth(struct dcerpc_binding *b)
     406             : {
     407          14 :         NTSTATUS status = dcerpc_binding_set_flags(
     408             :                 b,
     409             :                 0,
     410             :                 DCERPC_PACKET|
     411             :                 DCERPC_CONNECT|
     412             :                 DCERPC_SIGN|
     413             :                 DCERPC_SEAL|
     414             :                 DCERPC_SCHANNEL|
     415             :                 DCERPC_AUTH_SPNEGO|
     416             :                 DCERPC_AUTH_KRB5|
     417             :                 DCERPC_AUTH_NTLM);
     418          14 :         return status;
     419             : }
     420             : 
     421          14 : static NTSTATUS binding_set_auth(
     422             :         struct dcerpc_binding *b, const char *level, const char *type)
     423             : {
     424             :         NTSTATUS status;
     425             : 
     426          14 :         status = binding_reset_auth(b);
     427          14 :         if (!NT_STATUS_IS_OK(status)) {
     428           0 :                 return status;
     429             :         }
     430             : 
     431          14 :         if (level != NULL) {
     432          14 :                 status = dcerpc_binding_set_string_option(b, level, level);
     433          14 :                 if (!NT_STATUS_IS_OK(status)) {
     434           0 :                         return status;
     435             :                 }
     436             :         }
     437             : 
     438          14 :         if (strequal(type, "SPNEGO")) {
     439           0 :                 status = dcerpc_binding_set_string_option(
     440             :                         b, "spnego", "spnego");
     441           0 :                 return status;
     442             :         }
     443          14 :         if (strequal(type, "NTLMSSP")) {
     444           0 :                 status = dcerpc_binding_set_string_option(b, "ntlm", "ntlm");
     445           0 :                 return status;
     446             :         }
     447          14 :         if (strequal(type, "NTLMSSP_SPNEGO")) {
     448           0 :                 status = dcerpc_binding_set_string_option(
     449             :                         b, "spnego", "spnego");
     450           0 :                 if (!NT_STATUS_IS_OK(status)) {
     451           0 :                         return status;
     452             :                 }
     453           0 :                 status = dcerpc_binding_set_string_option(b, "ntlm", "ntlm");
     454           0 :                 return status;
     455             :         }
     456          14 :         if (strequal(type, "KRB5")) {
     457           0 :                 status = dcerpc_binding_set_string_option(b, "krb5", "krb5");
     458           0 :                 return status;
     459             :         }
     460          14 :         if (strequal(type, "KRB5_SPNEGO")) {
     461           0 :                 status = dcerpc_binding_set_string_option(
     462             :                         b, "spnego", "spnego");
     463           0 :                 if (!NT_STATUS_IS_OK(status)) {
     464           0 :                         return status;
     465             :                 }
     466           0 :                 status = dcerpc_binding_set_string_option(b, "krb5", "krb5");
     467           0 :                 return status;
     468             :         }
     469          14 :         if (strequal(type, "SCHANNEL")) {
     470          14 :                 status = dcerpc_binding_set_string_option(
     471             :                         b, "schannel", "schannel");
     472          14 :                 return status;
     473             :         }
     474             : 
     475           0 :         return NT_STATUS_INVALID_PARAMETER;
     476             : }
     477             : 
     478          14 : static NTSTATUS cmd_set_auth(
     479             :         struct dcerpc_binding *binding,
     480             :         const char *level,
     481             :         const char *display,
     482             :         int argc,
     483             :         const char **argv)
     484             : {
     485          14 :         const char *p = "[KRB5|KRB5_SPNEGO|NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]";
     486          14 :         const char *type = "NTLMSSP";
     487             :         NTSTATUS status;
     488             : 
     489          14 :         if (argc > 2) {
     490           0 :                 printf("Usage: %s %s\n", argv[0], p);
     491           0 :                 return NT_STATUS_OK;
     492             :         }
     493             : 
     494          14 :         if (argc == 2) {
     495          14 :                 type = argv[1];
     496             :         }
     497             : 
     498          14 :         status = binding_set_auth(binding, level, type);
     499          14 :         if (!NT_STATUS_IS_OK(status)) {
     500           0 :                 printf("Usage: %s %s\n", argv[0], p);
     501           0 :                 return status;
     502             :         }
     503             : 
     504          14 :         d_printf("Setting %s - %s: %s\n", type, display, nt_errstr(status));
     505             : 
     506          14 :         status = cmd_set_ss_level(binding);
     507          14 :         return status;
     508             : }
     509             : 
     510           0 : static NTSTATUS cmd_sign(
     511             :         struct dcerpc_binding *binding,
     512             :         TALLOC_CTX *mem_ctx,
     513             :         int argc,
     514             :         const char **argv)
     515             : {
     516           0 :         NTSTATUS status = cmd_set_auth(binding, "sign", "sign", argc, argv);
     517           0 :         return status;
     518             : }
     519             : 
     520           0 : static NTSTATUS cmd_seal(
     521             :         struct dcerpc_binding *binding,
     522             :         TALLOC_CTX *mem_ctx,
     523             :         int argc,
     524             :         const char **argv)
     525             : {
     526           0 :         NTSTATUS status = cmd_set_auth(
     527             :                 binding, "seal", "sign and seal", argc, argv);
     528           0 :         return status;
     529             : }
     530             : 
     531           0 : static NTSTATUS cmd_packet(
     532             :         struct dcerpc_binding *binding,
     533             :         TALLOC_CTX *mem_ctx,
     534             :         int argc,
     535             :         const char **argv)
     536             : {
     537           0 :         NTSTATUS status = cmd_set_auth(
     538             :                 binding, "packet", "packet", argc, argv);
     539           0 :         return status;
     540             : }
     541             : 
     542           0 : static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
     543             :                             int argc, const char **argv)
     544             : {
     545           0 :         if (argc > 2) {
     546           0 :                 printf("Usage: %s timeout\n", argv[0]);
     547           0 :                 return NT_STATUS_OK;
     548             :         }
     549             : 
     550           0 :         if (argc == 2) {
     551           0 :                 timeout = atoi(argv[1]);
     552             :         }
     553             : 
     554           0 :         printf("timeout is %d\n", timeout);
     555             : 
     556           0 :         return NT_STATUS_OK;
     557             : }
     558             : 
     559             : 
     560           0 : static NTSTATUS cmd_none(
     561             :         struct dcerpc_binding *binding,
     562             :         TALLOC_CTX *mem_ctx,
     563             :         int argc,
     564             :         const char **argv)
     565             : {
     566           0 :         NTSTATUS status = binding_reset_auth(binding);
     567           0 :         if (!NT_STATUS_IS_OK(status)) {
     568           0 :                 return status;
     569             :         }
     570           0 :         status = cmd_set_ss_level(binding);
     571           0 :         return status;
     572             : }
     573             : 
     574           7 : static NTSTATUS cmd_schannel(
     575             :         struct dcerpc_binding *binding,
     576             :         TALLOC_CTX *mem_ctx,
     577             :         int argc,
     578             :         const char **_argv)
     579             : {
     580           7 :         const char *argv[] = { "schannel", "SCHANNEL" };
     581           7 :         NTSTATUS status = cmd_set_auth(
     582             :                 binding, "seal", "sign and seal", 2, argv);
     583           7 :         return status;
     584             : }
     585             : 
     586           7 : static NTSTATUS cmd_schannel_sign(
     587             :         struct dcerpc_binding *binding,
     588             :         TALLOC_CTX *mem_ctx,
     589             :         int argc,
     590             :         const char **_argv)
     591             : {
     592           7 :         const char *argv[] = { "schannel_sign", "SCHANNEL" };
     593           7 :         NTSTATUS status = cmd_set_auth(binding, "sign", "sign only", 2, argv);
     594           7 :         return status;
     595             : }
     596             : 
     597           0 : static NTSTATUS cmd_choose_transport(
     598             :         struct dcerpc_binding *binding,
     599             :         TALLOC_CTX *mem_ctx,
     600             :         int argc,
     601             :         const char **argv)
     602             : {
     603             :         NTSTATUS status;
     604             :         enum dcerpc_transport_t transport;
     605             : 
     606           0 :         if (argc != 2) {
     607           0 :                 printf("Usage: %s [NCACN_NP|NCACN_IP_TCP]\n", argv[0]);
     608           0 :                 return NT_STATUS_OK;
     609             :         }
     610             : 
     611           0 :         transport = dcerpc_transport_by_name(argv[1]);
     612           0 :         if (transport == NCA_UNKNOWN) {
     613           0 :                 printf("transport type %s unknown\n", argv[1]);
     614           0 :                 return NT_STATUS_NOT_SUPPORTED;
     615             :         }
     616           0 :         if (!((transport == NCACN_IP_TCP) ||
     617             :               (transport == NCACN_NP) ||
     618             :               (transport == NCALRPC))) {
     619           0 :                 printf("transport %s not supported\n", argv[1]);
     620           0 :                 return NT_STATUS_NOT_SUPPORTED;
     621             :         }
     622             : 
     623           0 :         status = dcerpc_binding_set_transport(binding, transport);
     624           0 :         if (!NT_STATUS_IS_OK(status)) {
     625           0 :                 return status;
     626             :         }
     627             : 
     628           0 :         status = cmd_set_transport(binding);
     629           0 :         if (!NT_STATUS_IS_OK(status)) {
     630           0 :                 return status;
     631             :         }
     632             : 
     633           0 :         printf("default transport is now: %s\n", argv[1]);
     634             : 
     635           0 :         return NT_STATUS_OK;
     636             : }
     637             : 
     638             : /* Built in rpcclient commands */
     639             : 
     640             : static struct cmd_set rpcclient_commands[] = {
     641             : 
     642             :         {
     643             :                 .name = "GENERAL OPTIONS",
     644             :         },
     645             : 
     646             :         {
     647             :                 .name               = "help",
     648             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     649             :                 .ntfn               = cmd_help,
     650             :                 .description        = "Get help on commands",
     651             :                 .usage              = "[command]",
     652             :         },
     653             :         {
     654             :                 .name               = "?",
     655             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     656             :                 .ntfn               = cmd_help,
     657             :                 .description        = "Get help on commands",
     658             :                 .usage              = "[command]",
     659             :         },
     660             :         {
     661             :                 .name               = "debuglevel",
     662             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     663             :                 .ntfn               = cmd_debuglevel,
     664             :                 .description        = "Set debug level",
     665             :                 .usage              = "level",
     666             :         },
     667             :         {
     668             :                 .name               = "debug",
     669             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     670             :                 .ntfn               = cmd_debuglevel,
     671             :                 .description        = "Set debug level",
     672             :                 .usage              = "level",
     673             :         },
     674             :         {
     675             :                 .name               = "list",
     676             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     677             :                 .ntfn               = cmd_listcommands,
     678             :                 .description        = "List available commands on <pipe>",
     679             :                 .usage              = "pipe",
     680             :         },
     681             :         {
     682             :                 .name               = "exit",
     683             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     684             :                 .ntfn               = cmd_quit,
     685             :                 .description        = "Exit program",
     686             :                 .usage              = "",
     687             :         },
     688             :         {
     689             :                 .name               = "quit",
     690             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     691             :                 .ntfn               = cmd_quit,
     692             :                 .description        = "Exit program",
     693             :                 .usage              = "",
     694             :         },
     695             :         {
     696             :                 .name               = "sign",
     697             :                 .returntype         = RPC_RTYPE_BINDING,
     698             :                 .bfn                = cmd_sign,
     699             :                 .description        = "Force RPC pipe connections to be signed",
     700             :                 .usage              = "",
     701             :         },
     702             :         {
     703             :                 .name               = "seal",
     704             :                 .returntype         = RPC_RTYPE_BINDING,
     705             :                 .bfn                = cmd_seal,
     706             :                 .description        = "Force RPC pipe connections to be sealed",
     707             :                 .usage              = "",
     708             :         },
     709             :         {
     710             :                 .name               = "packet",
     711             :                 .returntype         = RPC_RTYPE_BINDING,
     712             :                 .bfn                = cmd_packet,
     713             :                 .description        = "Force RPC pipe connections with packet authentication level",
     714             :                 .usage              = "",
     715             :         },
     716             :         {
     717             :                 .name               = "schannel",
     718             :                 .returntype         = RPC_RTYPE_BINDING,
     719             :                 .bfn                = cmd_schannel,
     720             :                 .description        = "Force RPC pipe connections to be sealed with 'schannel'. "
     721             :                                       "Assumes valid machine account to this domain controller.",
     722             :                 .usage              = "",
     723             :         },
     724             :         {
     725             :                 .name               = "schannelsign",
     726             :                 .returntype         = RPC_RTYPE_BINDING,
     727             :                 .bfn                = cmd_schannel_sign,
     728             :                 .description        = "Force RPC pipe connections to be signed (not sealed) with "
     729             :                                       "'schannel'.  Assumes valid machine account to this domain "
     730             :                                       "controller.",
     731             :                 .usage              = "",
     732             :         },
     733             :         {
     734             :                 .name               = "timeout",
     735             :                 .returntype         = RPC_RTYPE_NTSTATUS,
     736             :                 .ntfn               = cmd_timeout,
     737             :                 .description        = "Set timeout (in milliseconds) for RPC operations",
     738             :                 .usage              = "",
     739             :         },
     740             :         {
     741             :                 .name               = "transport",
     742             :                 .returntype         = RPC_RTYPE_BINDING,
     743             :                 .bfn                = cmd_choose_transport,
     744             :                 .description        = "Choose ncacn transport for RPC operations",
     745             :                 .usage              = "",
     746             :         },
     747             :         {
     748             :                 .name               = "none",
     749             :                 .returntype         = RPC_RTYPE_BINDING,
     750             :                 .bfn                = cmd_none,
     751             :                 .description        = "Force RPC pipe connections to have no special properties",
     752             :                 .usage              = "",
     753             :         },
     754             : 
     755             :         { .name = NULL, },
     756             : };
     757             : 
     758             : static struct cmd_set separator_command[] = {
     759             :         {
     760             :                 .name               = "---------------",
     761             :                 .returntype         = MAX_RPC_RETURN_TYPE,
     762             :                 .description        = "----------------------"
     763             :         },
     764             :         { .name = NULL, },
     765             : };
     766             : 
     767             : 
     768             : /* Various pipe commands */
     769             : 
     770             : extern struct cmd_set lsarpc_commands[];
     771             : extern struct cmd_set samr_commands[];
     772             : extern struct cmd_set spoolss_commands[];
     773             : extern struct cmd_set iremotewinspool_commands[];
     774             : extern struct cmd_set netlogon_commands[];
     775             : extern struct cmd_set srvsvc_commands[];
     776             : extern struct cmd_set dfs_commands[];
     777             : extern struct cmd_set ds_commands[];
     778             : extern struct cmd_set echo_commands[];
     779             : extern struct cmd_set epmapper_commands[];
     780             : extern struct cmd_set shutdown_commands[];
     781             : extern struct cmd_set wkssvc_commands[];
     782             : extern struct cmd_set ntsvcs_commands[];
     783             : extern struct cmd_set drsuapi_commands[];
     784             : extern struct cmd_set eventlog_commands[];
     785             : extern struct cmd_set winreg_commands[];
     786             : extern struct cmd_set fss_commands[];
     787             : extern struct cmd_set witness_commands[];
     788             : extern struct cmd_set clusapi_commands[];
     789             : extern struct cmd_set spotlight_commands[];
     790             : extern struct cmd_set unixinfo_commands[];
     791             : 
     792             : static struct cmd_set *rpcclient_command_list[] = {
     793             :         rpcclient_commands,
     794             :         lsarpc_commands,
     795             :         ds_commands,
     796             :         samr_commands,
     797             :         spoolss_commands,
     798             :         iremotewinspool_commands,
     799             :         netlogon_commands,
     800             :         srvsvc_commands,
     801             :         dfs_commands,
     802             :         echo_commands,
     803             :         epmapper_commands,
     804             :         shutdown_commands,
     805             :         wkssvc_commands,
     806             :         ntsvcs_commands,
     807             :         drsuapi_commands,
     808             :         eventlog_commands,
     809             :         winreg_commands,
     810             :         fss_commands,
     811             :         witness_commands,
     812             :         clusapi_commands,
     813             :         spotlight_commands,
     814             :         unixinfo_commands,
     815             :         NULL
     816             : };
     817             : 
     818       30448 : static void add_command_set(struct cmd_set *cmd_set)
     819             : {
     820             :         struct cmd_list *entry;
     821             : 
     822       30448 :         if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
     823           0 :                 DEBUG(0, ("out of memory\n"));
     824           0 :                 return;
     825             :         }
     826             : 
     827       30448 :         ZERO_STRUCTP(entry);
     828             : 
     829       30448 :         entry->cmd_set = cmd_set;
     830       30448 :         DLIST_ADD(cmd_list, entry);
     831             : }
     832             : 
     833         152 : static NTSTATUS rpccli_ncalrpc_connect(
     834             :         const struct ndr_interface_table *iface,
     835             :         TALLOC_CTX *mem_ctx,
     836             :         struct rpc_pipe_client **prpccli)
     837             : {
     838         152 :         struct rpc_pipe_client *rpccli = NULL;
     839         152 :         struct pipe_auth_data *auth = NULL;
     840             :         NTSTATUS status;
     841             : 
     842         152 :         status = rpc_pipe_open_ncalrpc(mem_ctx, iface, &rpccli);
     843         152 :         if (!NT_STATUS_IS_OK(status)) {
     844          16 :                 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
     845             :                           nt_errstr(status));
     846          16 :                 goto fail;
     847             :         }
     848             : 
     849         136 :         status = rpccli_ncalrpc_bind_data(rpccli, &auth);
     850         136 :         if (!NT_STATUS_IS_OK(status)) {
     851           0 :                 DBG_DEBUG("rpccli_ncalrpc_bind_data failed: %s\n",
     852             :                           nt_errstr(status));
     853           0 :                 goto fail;
     854             :         }
     855             : 
     856         136 :         status = rpc_pipe_bind(rpccli, auth);
     857         136 :         if (!NT_STATUS_IS_OK(status)) {
     858           0 :                 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
     859           0 :                 goto fail;
     860             :         }
     861             : 
     862         136 :         *prpccli = rpccli;
     863         136 :         return NT_STATUS_OK;
     864          16 : fail:
     865          16 :         TALLOC_FREE(rpccli);
     866          16 :         return status;
     867             : }
     868             : /**
     869             :  * Call an rpcclient function, passing an argv array.
     870             :  *
     871             :  * @param cmd Command to run, as a single string.
     872             :  **/
     873         716 : static NTSTATUS do_cmd(struct cli_state *cli,
     874             :                        struct cli_credentials *creds,
     875             :                        struct cmd_set *cmd_entry,
     876             :                        struct dcerpc_binding *binding,
     877             :                        int argc, const char **argv)
     878             : {
     879             :         NTSTATUS ntresult;
     880             :         WERROR wresult;
     881             :         enum dcerpc_transport_t transport;
     882             : 
     883         716 :         TALLOC_CTX *mem_ctx = talloc_stackframe();
     884         716 :         const char *remote_name = NULL;
     885         716 :         const struct sockaddr_storage *remote_sockaddr = NULL;
     886         716 :         struct sockaddr_storage remote_ss = {
     887             :                 .ss_family = AF_UNSPEC,
     888             :         };
     889             : 
     890         716 :         transport = dcerpc_binding_get_transport(binding);
     891             : 
     892         716 :         if (cli != NULL) {
     893         466 :                 remote_name = smbXcli_conn_remote_name(cli->conn);
     894         466 :                 remote_sockaddr = smbXcli_conn_remote_sockaddr(cli->conn);
     895             :         } else {
     896             :                 const char *remote_host =
     897         250 :                         dcerpc_binding_get_string_option(binding, "host");
     898         250 :                 remote_name = dcerpc_binding_get_string_option(
     899             :                                 binding, "target_hostname");
     900             : 
     901         250 :                 if (remote_host != NULL) {
     902          98 :                         bool ok = interpret_string_addr(
     903             :                                 &remote_ss, remote_host, 0);
     904          98 :                         if (ok) {
     905          98 :                                 remote_sockaddr = &remote_ss;
     906             :                         }
     907             :                 }
     908             :         }
     909             : 
     910             :         /* Open pipe */
     911             : 
     912         716 :         if ((cmd_entry->table != NULL) && (cmd_entry->rpc_pipe == NULL)) {
     913         692 :                 if (transport == NCALRPC) {
     914         152 :                         ntresult = rpccli_ncalrpc_connect(
     915             :                                 cmd_entry->table, cli, &cmd_entry->rpc_pipe);
     916         152 :                         if (!NT_STATUS_IS_OK(ntresult)) {
     917          16 :                                 TALLOC_FREE(mem_ctx);
     918          16 :                                 return ntresult;
     919             :                         }
     920             :                 } else {
     921             :                         enum dcerpc_AuthType auth_type;
     922             :                         enum dcerpc_AuthLevel auth_level;
     923         540 :                         enum credentials_use_kerberos krb5_state =
     924         540 :                                 cli_credentials_get_kerberos_state(creds);
     925             : 
     926         540 :                         binding_get_auth_info(
     927             :                                 binding, &auth_type, &auth_level, &krb5_state);
     928             : 
     929         540 :                         switch (auth_type) {
     930         295 :                         case DCERPC_AUTH_TYPE_NONE:
     931         295 :                                 ntresult = cli_rpc_pipe_open_noauth_transport(
     932             :                                         cli, transport,
     933             :                                         cmd_entry->table,
     934             :                                         remote_name,
     935             :                                         remote_sockaddr,
     936             :                                         &cmd_entry->rpc_pipe);
     937         295 :                                 break;
     938         227 :                         case DCERPC_AUTH_TYPE_SPNEGO:
     939             :                         case DCERPC_AUTH_TYPE_NTLMSSP:
     940             :                         case DCERPC_AUTH_TYPE_KRB5:
     941         227 :                                 cli_credentials_set_kerberos_state(creds,
     942             :                                                                    krb5_state,
     943             :                                                                    CRED_SPECIFIED);
     944             : 
     945         227 :                                 ntresult = cli_rpc_pipe_open_with_creds(
     946             :                                         cli, cmd_entry->table,
     947             :                                         transport,
     948             :                                         auth_type,
     949             :                                         auth_level,
     950             :                                         remote_name,
     951             :                                         remote_sockaddr,
     952             :                                         creds,
     953             :                                         &cmd_entry->rpc_pipe);
     954         227 :                                 break;
     955          18 :                         case DCERPC_AUTH_TYPE_SCHANNEL:
     956          18 :                                 TALLOC_FREE(rpcclient_netlogon_creds);
     957          18 :                                 ntresult = cli_rpc_pipe_open_schannel(
     958             :                                         cli, rpcclient_msg_ctx,
     959             :                                         cmd_entry->table,
     960             :                                         transport,
     961             :                                         rpcclient_netlogon_domain,
     962             :                                         remote_name,
     963             :                                         remote_sockaddr,
     964             :                                         &cmd_entry->rpc_pipe,
     965             :                                         rpcclient_msg_ctx,
     966             :                                         &rpcclient_netlogon_creds);
     967          18 :                                 break;
     968           0 :                         default:
     969           0 :                                 DEBUG(0, ("Could not initialise %s. Invalid "
     970             :                                           "auth type %u\n",
     971             :                                           cmd_entry->table->name,
     972             :                                           auth_type ));
     973           0 :                                 talloc_free(mem_ctx);
     974           0 :                                 return NT_STATUS_UNSUCCESSFUL;
     975             :                         }
     976         540 :                         if (!NT_STATUS_IS_OK(ntresult)) {
     977           0 :                                 DBG_ERR("Could not initialise %s. "
     978             :                                         "Error was %s\n",
     979             :                                         cmd_entry->table->name,
     980             :                                         nt_errstr(ntresult));
     981           0 :                                 talloc_free(mem_ctx);
     982           0 :                                 return ntresult;
     983             :                         }
     984             : 
     985         540 :                         if (rpcclient_netlogon_creds == NULL &&
     986         522 :                             cmd_entry->use_netlogon_creds) {
     987          18 :                                 const char *dc_name =
     988          18 :                                         cmd_entry->rpc_pipe->desthost;
     989          18 :                                 const char *domain = rpcclient_netlogon_domain;
     990          18 :                                 struct cli_credentials *trust_creds = NULL;
     991             : 
     992          18 :                                 ntresult = pdb_get_trust_credentials(
     993             :                                         domain,
     994             :                                         NULL,
     995             :                                         mem_ctx,
     996             :                                         &trust_creds);
     997          18 :                                 if (!NT_STATUS_IS_OK(ntresult)) {
     998           0 :                                         DBG_ERR("Failed to fetch trust "
     999             :                                                 "credentials for "
    1000             :                                                 "%s to connect to %s: %s\n",
    1001             :                                                 domain,
    1002             :                                                 cmd_entry->table->name,
    1003             :                                                 nt_errstr(ntresult));
    1004           0 :                                         TALLOC_FREE(cmd_entry->rpc_pipe);
    1005           0 :                                         talloc_free(mem_ctx);
    1006           0 :                                         return ntresult;
    1007             :                                 }
    1008             : 
    1009          18 :                                 ntresult = rpccli_create_netlogon_creds_ctx(
    1010             :                                         trust_creds,
    1011             :                                         dc_name,
    1012             :                                         rpcclient_msg_ctx,
    1013             :                                         rpcclient_msg_ctx,
    1014             :                                         &rpcclient_netlogon_creds);
    1015          18 :                                 if (!NT_STATUS_IS_OK(ntresult)) {
    1016           0 :                                         DBG_ERR("Could not initialise "
    1017             :                                                 "credentials for %s.\n",
    1018             :                                                 cmd_entry->table->name);
    1019           0 :                                         TALLOC_FREE(cmd_entry->rpc_pipe);
    1020           0 :                                         TALLOC_FREE(mem_ctx);
    1021           0 :                                         return ntresult;
    1022             :                                 }
    1023             : 
    1024          18 :                                 ntresult = rpccli_setup_netlogon_creds(
    1025             :                                         cli,
    1026             :                                         NCACN_NP,
    1027             :                                         rpcclient_netlogon_creds,
    1028             :                                         false, /* force_reauth */
    1029             :                                         trust_creds);
    1030          18 :                                 TALLOC_FREE(trust_creds);
    1031          18 :                                 if (!NT_STATUS_IS_OK(ntresult)) {
    1032           0 :                                         DBG_ERR("Could not initialise "
    1033             :                                                 "credentials for %s.\n",
    1034             :                                                 cmd_entry->table->name);
    1035           0 :                                         TALLOC_FREE(cmd_entry->rpc_pipe);
    1036           0 :                                         TALLOC_FREE(rpcclient_netlogon_creds);
    1037           0 :                                         TALLOC_FREE(mem_ctx);
    1038           0 :                                         return ntresult;
    1039             :                                 }
    1040             :                         }
    1041             :                 }
    1042             :         }
    1043             : 
    1044             :         /* Set timeout for new connections */
    1045         700 :         if (cmd_entry->rpc_pipe) {
    1046         686 :                 rpccli_set_timeout(cmd_entry->rpc_pipe, timeout);
    1047             :         }
    1048             : 
    1049             :         /* Run command */
    1050             : 
    1051         700 :         if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
    1052         609 :                 ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, argv);
    1053         609 :                 if (!NT_STATUS_IS_OK(ntresult)) {
    1054          64 :                         printf("result was %s\n", nt_errstr(ntresult));
    1055             :                 }
    1056          91 :         } else if (cmd_entry->returntype == RPC_RTYPE_BINDING) {
    1057          14 :                 ntresult = cmd_entry->bfn(binding, mem_ctx, argc, argv);
    1058          14 :                 if (!NT_STATUS_IS_OK(ntresult)) {
    1059           0 :                         printf("result was %s\n", nt_errstr(ntresult));
    1060             :                 }
    1061             :         } else {
    1062          77 :                 wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, argv);
    1063             :                 /* print out the DOS error */
    1064          77 :                 if (!W_ERROR_IS_OK(wresult)) {
    1065           5 :                         printf( "result was %s\n", win_errstr(wresult));
    1066             :                 }
    1067          77 :                 ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
    1068             :         }
    1069             : 
    1070             :         /* Cleanup */
    1071             : 
    1072         700 :         talloc_free(mem_ctx);
    1073             : 
    1074         700 :         return ntresult;
    1075             : }
    1076             : 
    1077             : 
    1078             : /**
    1079             :  * Process a command entered at the prompt or as part of -c
    1080             :  *
    1081             :  * @returns The NTSTATUS from running the command.
    1082             :  **/
    1083         716 : static NTSTATUS process_cmd(struct cli_credentials *creds,
    1084             :                             struct cli_state *cli,
    1085             :                             struct dcerpc_binding *binding,
    1086             :                             char *cmd)
    1087             : {
    1088             :         struct cmd_list *temp_list;
    1089         716 :         NTSTATUS result = NT_STATUS_OK;
    1090             :         int ret;
    1091             :         int argc;
    1092         716 :         const char **argv = NULL;
    1093             : 
    1094         716 :         if ((ret = poptParseArgvString(cmd, &argc, &argv)) != 0) {
    1095           0 :                 fprintf(stderr, "rpcclient: %s\n", poptStrerror(ret));
    1096           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1097             :         }
    1098             : 
    1099             : 
    1100             :         /* Walk through a dlist of arrays of commands. */
    1101       24324 :         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
    1102       24324 :                 struct cmd_set *set = temp_list->cmd_set;
    1103             : 
    1104      143632 :                 while (set->name != NULL) {
    1105      120024 :                         if (!strequal(argv[0], set->name)) {
    1106      119308 :                                 set += 1;
    1107      119308 :                                 continue;
    1108             :                         }
    1109             : 
    1110         716 :                         if (((set->returntype == RPC_RTYPE_NTSTATUS) &&
    1111         625 :                              (set->ntfn == NULL)) ||
    1112         716 :                             ((set->returntype == RPC_RTYPE_WERROR) &&
    1113          77 :                              (set->wfn == NULL)) ||
    1114         716 :                             ((set->returntype == RPC_RTYPE_BINDING) &&
    1115          14 :                              (set->bfn == NULL))) {
    1116           0 :                                 fprintf (stderr, "Invalid command\n");
    1117           0 :                                 goto out_free;
    1118             :                         }
    1119             : 
    1120         716 :                         result = do_cmd(
    1121             :                                 cli, creds, set, binding, argc, argv);
    1122         716 :                         goto out_free;
    1123             :                 }
    1124             :         }
    1125             : 
    1126           0 :         if (argv[0]) {
    1127           0 :                 printf("command not found: %s\n", argv[0]);
    1128             :         }
    1129             : 
    1130           0 : out_free:
    1131             : /* moved to do_cmd()
    1132             :         if (!NT_STATUS_IS_OK(result)) {
    1133             :                 printf("result was %s\n", nt_errstr(result));
    1134             :         }
    1135             : */
    1136             : 
    1137             :         /* NOTE: popt allocates the whole argv, including the
    1138             :          * strings, as a single block.  So a single free is
    1139             :          * enough to release it -- we don't free the
    1140             :          * individual strings.  rtfm. */
    1141         716 :         free(argv);
    1142             : 
    1143         716 :         return result;
    1144             : }
    1145             : 
    1146             : 
    1147             : /* Main function */
    1148             : 
    1149         719 :  int main(int argc, char *argv[])
    1150             : {
    1151         719 :         const char **const_argv = discard_const_p(const char *, argv);
    1152             :         int                     opt;
    1153             :         static char             *cmdstr = NULL;
    1154             :         const char *server;
    1155         719 :         struct cli_state        *cli = NULL;
    1156             :         static char             *opt_ipaddr=NULL;
    1157             :         struct cmd_set          **cmd_set;
    1158             :         struct sockaddr_storage server_ss;
    1159             :         NTSTATUS                nt_status;
    1160             :         static int              opt_port = 0;
    1161         719 :         int result = 0;
    1162         719 :         TALLOC_CTX *frame = talloc_stackframe();
    1163         719 :         uint32_t flags = CLI_FULL_CONNECTION_IPC;
    1164         719 :         struct dcerpc_binding *binding = NULL;
    1165             :         enum dcerpc_transport_t transport;
    1166         719 :         const char *binding_string = NULL;
    1167             :         const char *host;
    1168         719 :         struct cli_credentials *creds = NULL;
    1169         719 :         struct loadparm_context *lp_ctx = NULL;
    1170             :         bool ok;
    1171             : 
    1172             :         /* make sure the vars that get altered (4th field) are in
    1173             :            a fixed location or certain compilers complain */
    1174             :         poptContext pc;
    1175        4314 :         struct poptOption long_options[] = {
    1176             :                 POPT_AUTOHELP
    1177             :                 {"command",   'c', POPT_ARG_STRING,   &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
    1178             :                 {"dest-ip", 'I', POPT_ARG_STRING,   &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
    1179             :                 {"port", 'p', POPT_ARG_INT,   &opt_port, 'p', "Specify port number", "PORT"},
    1180         719 :                 POPT_COMMON_SAMBA
    1181         719 :                 POPT_COMMON_CONNECTION
    1182         719 :                 POPT_COMMON_CREDENTIALS
    1183         719 :                 POPT_LEGACY_S3
    1184         719 :                 POPT_COMMON_VERSION
    1185             :                 POPT_TABLEEND
    1186             :         };
    1187             : 
    1188         719 :         smb_init_locale();
    1189             : 
    1190         719 :         zero_sockaddr(&server_ss);
    1191             : 
    1192         719 :         setlinebuf(stdout);
    1193             : 
    1194         719 :         ok = samba_cmdline_init(frame,
    1195             :                                 SAMBA_CMDLINE_CONFIG_CLIENT,
    1196             :                                 false /* require_smbconf */);
    1197         719 :         if (!ok) {
    1198           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
    1199             :         }
    1200         719 :         lp_ctx = samba_cmdline_get_lp_ctx();
    1201         719 :         lpcfg_set_cmdline(lp_ctx, "log level", "0");
    1202             : 
    1203             :         /* Parse options */
    1204         719 :         pc = samba_popt_get_context(getprogname(),
    1205             :                                     argc,
    1206             :                                     const_argv,
    1207             :                                     long_options,
    1208             :                                     0);
    1209         719 :         if (pc == NULL) {
    1210           0 :                 DBG_ERR("Failed to setup popt context!\n");
    1211           0 :                 exit(1);
    1212             :         }
    1213             : 
    1214         719 :         poptSetOtherOptionHelp(pc, "[OPTION...] BINDING-STRING|HOST\nOptions:");
    1215             : 
    1216         719 :         if (argc == 1) {
    1217           0 :                 poptPrintHelp(pc, stderr, 0);
    1218           0 :                 goto done;
    1219             :         }
    1220             : 
    1221        1553 :         while((opt = poptGetNextOpt(pc)) != -1) {
    1222         719 :                 switch (opt) {
    1223             : 
    1224           0 :                 case 'I':
    1225           0 :                         if (!interpret_string_addr(&server_ss,
    1226             :                                                 opt_ipaddr,
    1227             :                                                 AI_NUMERICHOST)) {
    1228           0 :                                 fprintf(stderr, "%s not a valid IP address\n",
    1229             :                                         opt_ipaddr);
    1230           0 :                                 result = 1;
    1231           0 :                                 goto done;
    1232             :                         }
    1233           0 :                         break;
    1234           0 :                 case POPT_ERROR_BADOPT:
    1235           0 :                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
    1236             :                                 poptBadOption(pc, 0), poptStrerror(opt));
    1237           0 :                         poptPrintUsage(pc, stderr, 0);
    1238           0 :                         exit(1);
    1239             :                 }
    1240             :         }
    1241             : 
    1242             :         /* Get server as remaining unparsed argument.  Print usage if more
    1243             :            than one unparsed argument is present. */
    1244             : 
    1245         719 :         server = talloc_strdup(frame, poptGetArg(pc));
    1246             : 
    1247         719 :         if (!server || poptGetArg(pc)) {
    1248           0 :                 poptPrintHelp(pc, stderr, 0);
    1249           0 :                 result = 1;
    1250           0 :                 goto done;
    1251             :         }
    1252             : 
    1253         719 :         poptFreeContext(pc);
    1254         719 :         samba_cmdline_burn(argc, argv);
    1255             : 
    1256         719 :         rpcclient_msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
    1257         719 :         creds = samba_cmdline_get_creds();
    1258             : 
    1259             :         /*
    1260             :          * Get password
    1261             :          * from stdin if necessary
    1262             :          */
    1263             : 
    1264         719 :         if ((server[0] == '/' && server[1] == '/') ||
    1265         711 :                         (server[0] == '\\' && server[1] ==  '\\')) {
    1266           8 :                 server += 2;
    1267             :         }
    1268             : 
    1269         719 :         nt_status = dcerpc_parse_binding(frame, server, &binding);
    1270             : 
    1271         719 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1272             : 
    1273           0 :                 binding_string = talloc_asprintf(frame, "ncacn_np:%s",
    1274             :                                                  strip_hostname(server));
    1275           0 :                 if (!binding_string) {
    1276           0 :                         result = 1;
    1277           0 :                         goto done;
    1278             :                 }
    1279             : 
    1280           0 :                 nt_status = dcerpc_parse_binding(frame, binding_string, &binding);
    1281           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1282           0 :                         result = -1;
    1283           0 :                         goto done;
    1284             :                 }
    1285             :         }
    1286             : 
    1287         719 :         transport = dcerpc_binding_get_transport(binding);
    1288             : 
    1289         719 :         if (transport == NCA_UNKNOWN) {
    1290         249 :                 transport = NCACN_NP;
    1291         249 :                 nt_status = dcerpc_binding_set_transport(binding, transport);
    1292         249 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1293           0 :                         result = -1;
    1294           0 :                         goto done;
    1295             :                 }
    1296             :         }
    1297             : 
    1298         719 :         host = dcerpc_binding_get_string_option(binding, "host");
    1299             : 
    1300         719 :         rpcclient_netlogon_domain = cli_credentials_get_domain(creds);
    1301         719 :         if (rpcclient_netlogon_domain == NULL ||
    1302         719 :             rpcclient_netlogon_domain[0] == '\0')
    1303             :         {
    1304          46 :                 rpcclient_netlogon_domain = lp_workgroup();
    1305             :         }
    1306             : 
    1307         719 :         if (transport == NCACN_NP) {
    1308         469 :                 nt_status = cli_full_connection_creds(
    1309             :                         &cli,
    1310             :                         lp_netbios_name(),
    1311             :                         host,
    1312         469 :                         opt_ipaddr ? &server_ss : NULL,
    1313             :                         opt_port,
    1314             :                         "IPC$",
    1315             :                         "IPC",
    1316             :                         creds,
    1317             :                         flags);
    1318             : 
    1319         469 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1320          27 :                         DEBUG(0, ("Cannot connect to server.  Error was %s\n",
    1321             :                                   nt_errstr(nt_status)));
    1322          27 :                         result = 1;
    1323          27 :                         goto done;
    1324             :                 }
    1325             : 
    1326             :                 /* Load command lists */
    1327         442 :                 cli_set_timeout(cli, timeout);
    1328             :         }
    1329             : 
    1330             : #if 0   /* COMMENT OUT FOR TESTING */
    1331             :         memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
    1332             : #endif
    1333             : 
    1334         692 :         cmd_set = rpcclient_command_list;
    1335             : 
    1336       15916 :         while(*cmd_set) {
    1337       15224 :                 add_command_set(*cmd_set);
    1338       15224 :                 add_command_set(separator_command);
    1339       15224 :                 cmd_set++;
    1340             :         }
    1341             : 
    1342             :        /* Do anything specified with -c */
    1343         692 :         if (cmdstr && cmdstr[0]) {
    1344             :                 char    *cmd;
    1345         692 :                 char    *p = cmdstr;
    1346             : 
    1347         692 :                 result = 0;
    1348             : 
    1349        1408 :                 while((cmd=next_command(&p)) != NULL) {
    1350         716 :                         NTSTATUS cmd_result = process_cmd(creds,
    1351             :                                                           cli,
    1352             :                                                           binding,
    1353             :                                                           cmd);
    1354         716 :                         SAFE_FREE(cmd);
    1355         716 :                         result = NT_STATUS_IS_ERR(cmd_result);
    1356             :                 }
    1357             : 
    1358         692 :                 goto done;
    1359             :         }
    1360             : 
    1361             :         /* Loop around accepting commands */
    1362             : 
    1363           0 :         while(1) {
    1364           0 :                 char *line = NULL;
    1365             : 
    1366           0 :                 line = smb_readline("rpcclient $> ", NULL, completion_fn);
    1367             : 
    1368           0 :                 if (line == NULL) {
    1369           0 :                         printf("\n");
    1370           0 :                         break;
    1371             :                 }
    1372             : 
    1373           0 :                 if (line[0] != '\n')
    1374           0 :                         process_cmd(creds,
    1375             :                                     cli,
    1376             :                                     binding,
    1377             :                                     line);
    1378           0 :                 SAFE_FREE(line);
    1379             :         }
    1380             : 
    1381         719 : done:
    1382         719 :         if (cli != NULL) {
    1383         442 :                 cli_shutdown(cli);
    1384             :         }
    1385         719 :         netlogon_creds_cli_close_global_db();
    1386         719 :         TALLOC_FREE(rpcclient_msg_ctx);
    1387         719 :         TALLOC_FREE(frame);
    1388         719 :         return result;
    1389             : }

Generated by: LCOV version 1.14