[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / rpcclient / rpcclient.c
index 2338d72f19273cf3941ff8dd8150cff0bb50196d..7a7b463b717087abbf15fb72129cbaacc1c1c724 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -25,6 +24,9 @@
 
 DOM_SID domain_sid;
 
+static enum pipe_auth_type pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
+static enum pipe_auth_level pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
+static unsigned int timeout = 0;
 
 /* List to hold groups of commands.
  *
@@ -40,7 +42,7 @@ static struct cmd_list {
 /****************************************************************************
 handle completion of commands for readline
 ****************************************************************************/
-static char **completion_fn(char *text, int start, int end)
+static char **completion_fn(const char *text, int start, int end)
 {
 #define MAX_COMPLETIONS 100
        char **matches;
@@ -56,114 +58,58 @@ static char **completion_fn(char *text, int start, int end)
 #endif
 
        /* make sure we have a list of valid commands */
-       if (!commands) 
+       if (!commands) {
                return NULL;
+       }
 
-       matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
-       if (!matches) return NULL;
+       matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
+       if (!matches) {
+               return NULL;
+       }
 
-       matches[count++] = strdup(text);
-       if (!matches[0]) return NULL;
+       matches[count++] = SMB_STRDUP(text);
+       if (!matches[0]) {
+               SAFE_FREE(matches);
+               return NULL;
+       }
 
-       while (commands && count < MAX_COMPLETIONS-1) 
-       {
-               if (!commands->cmd_set)
+       while (commands && count < MAX_COMPLETIONS-1) {
+               if (!commands->cmd_set) {
                        break;
+               }
                
-               for (i=0; commands->cmd_set[i].name; i++)
-               {
+               for (i=0; commands->cmd_set[i].name; i++) {
                        if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
                                (( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS &&
                         commands->cmd_set[i].ntfn ) || 
                       ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
-                        commands->cmd_set[i].wfn)))
-                       {
-                               matches[count] = strdup(commands->cmd_set[i].name);
-                               if (!matches[count]) 
+                        commands->cmd_set[i].wfn))) {
+                               matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
+                               if (!matches[count]) {
+                                       for (i = 0; i < count; i++) {
+                                               SAFE_FREE(matches[count]);
+                                       }
+                                       SAFE_FREE(matches);
                                        return NULL;
+                               }
                                count++;
                        }
                }
-               
                commands = commands->next;
                
        }
 
        if (count == 2) {
                SAFE_FREE(matches[0]);
-               matches[0] = strdup(matches[1]);
+               matches[0] = SMB_STRDUP(matches[1]);
        }
        matches[count] = NULL;
        return matches;
 }
 
-/***********************************************************************
- * read in username/password credentials from a file
- */
-static void read_authfile (
-       char *filename, 
-       char* username, 
-       char* password, 
-       char* domain
-)
+static char *next_command (char **cmdstr)
 {
-       FILE *auth;
-        fstring buf;
-        uint16 len = 0;
-       char *ptr, *val, *param;
-                               
-       if ((auth=sys_fopen(filename, "r")) == NULL)
-       {
-               printf ("ERROR: Unable to open credentials file!\n");
-               return;
-       }
-                                
-       while (!feof(auth))
-       {  
-               /* get a line from the file */
-               if (!fgets (buf, sizeof(buf), auth))
-                       continue;
-               
-               len = strlen(buf);
-               
-               /* skip empty lines */                  
-               if ((len) && (buf[len-1]=='\n'))
-               {
-                       buf[len-1] = '\0';
-                       len--;
-               }       
-               if (len == 0)
-                       continue;
-                                       
-               /* break up the line into parameter & value.
-                  will need to eat a little whitespace possibly */
-               param = buf;
-               if (!(ptr = strchr_m(buf, '=')))
-                       continue;
-               val = ptr+1;
-               *ptr = '\0';
-                                       
-               /* eat leading white space */
-               while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
-                       val++;
-                                       
-               if (strwicmp("password", param) == 0)
-                       fstrcpy (password, val);
-               else if (strwicmp("username", param) == 0)
-                       fstrcpy (username, val);
-               else if (strwicmp("domain", param) == 0)
-                       fstrcpy (domain, val);
-                                               
-               memset(buf, 0, sizeof(buf));
-       }
-       fclose(auth);
-       
-       return;
-}
-
-static char* next_command (char** cmdstr)
-{
-       static pstring          command;
+       char *command;
        char                    *p;
        
        if (!cmdstr || !(*cmdstr))
@@ -172,7 +118,7 @@ static char* next_command (char** cmdstr)
        p = strchr_m(*cmdstr, ';');
        if (p)
                *p = '\0';
-       pstrcpy(command, *cmdstr);
+       command = SMB_STRDUP(*cmdstr);
        if (p)
                *cmdstr = p + 1;
        else
@@ -181,28 +127,6 @@ static char* next_command (char** cmdstr)
        return command;
 }
 
-
-/**
- * Find default username from environment variables.
- *
- * @param username fstring to receive username; not touched if none is
- * known.
- **/
-static void get_username (char *username)
-{
-        if (getenv("USER"))
-                fstrcpy(username,getenv("USER"));
-        if (*username == 0 && getenv("LOGNAME"))
-                fstrcpy(username,getenv("LOGNAME"));
-        if (*username == 0) {
-                fstrcpy(username,"GUEST");
-        }
-
-       return;
-}
-
 /* Fetch the SID for this computer */
 
 static void fetch_machine_sid(struct cli_state *cli)
@@ -210,46 +134,52 @@ static void fetch_machine_sid(struct cli_state *cli)
        POLICY_HND pol;
        NTSTATUS result = NT_STATUS_OK;
        uint32 info_class = 5;
-       fstring domain_name;
+       char *domain_name = NULL;
        static BOOL got_domain_sid;
        TALLOC_CTX *mem_ctx;
+       DOM_SID *dom_sid = NULL;
+       struct rpc_pipe_client *lsapipe = NULL;
 
        if (got_domain_sid) return;
 
-       if (!(mem_ctx=talloc_init("fetch_machine_sid")))
-       {
+       if (!(mem_ctx=talloc_init("fetch_machine_sid"))) {
                DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n"));
                goto error;
        }
 
-
-       if (!cli_nt_session_open (cli, PI_LSARPC)) {
-               fprintf(stderr, "could not initialise lsa pipe\n");
+       if ((lsapipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result)) == NULL) {
+               fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) );
                goto error;
        }
        
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto error;
        }
 
-       result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
-                                          domain_name, &domain_sid);
+       result = rpccli_lsa_query_info_policy(lsapipe, mem_ctx, &pol, info_class, 
+                                          &domain_name, &dom_sid);
        if (!NT_STATUS_IS_OK(result)) {
                goto error;
        }
 
        got_domain_sid = True;
+       sid_copy( &domain_sid, dom_sid );
 
-       cli_lsa_close(cli, mem_ctx, &pol);
-       cli_nt_session_close(cli);
+       rpccli_lsa_Close(lsapipe, mem_ctx, &pol);
+       cli_rpc_pipe_close(lsapipe);
        talloc_destroy(mem_ctx);
 
        return;
 
  error:
+
+       if (lsapipe) {
+               cli_rpc_pipe_close(lsapipe);
+       }
+
        fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -261,7 +191,7 @@ static void fetch_machine_sid(struct cli_state *cli)
 
 /* List the available commands on a given pipe */
 
-static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 int argc, const char **argv)
 {
        struct cmd_list *tmp;
@@ -288,10 +218,10 @@ static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                        i = 0;
                        tmp_set++;
                        while(tmp_set->name) {
-                               printf("%20s", tmp_set->name);
+                               printf("%30s", tmp_set->name);
                                 tmp_set++;
                                i++;
-                               if (i%4 == 0)
+                               if (i%3 == 0)
                                        printf("\n");
                        }
                        
@@ -306,7 +236,7 @@ static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 /* Display help on commands */
 
-static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          int argc, const char **argv)
 {
        struct cmd_list *tmp;
@@ -366,7 +296,7 @@ static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 /* Change the debug level */
 
-static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                int argc, const char **argv)
 {
        if (argc > 2) {
@@ -383,31 +313,179 @@ static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS cmd_quit(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          int argc, const char **argv)
 {
        exit(0);
        return NT_STATUS_OK; /* NOTREACHED */
 }
 
+static NTSTATUS cmd_set_ss_level(void)
+{
+       struct cmd_list *tmp;
+
+       /* Close any existing connections not at this level. */
+
+       for (tmp = cmd_list; tmp; tmp = tmp->next) {
+               struct cmd_set *tmp_set;
+
+               for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
+                       if (tmp_set->rpc_pipe == NULL) {
+                               continue;
+                       }
+
+                       if (tmp_set->rpc_pipe->auth.auth_type != pipe_default_auth_type ||
+                                       tmp_set->rpc_pipe->auth.auth_level != pipe_default_auth_level) {
+                               cli_rpc_pipe_close(tmp_set->rpc_pipe);
+                               tmp_set->rpc_pipe = NULL;
+                       }
+               }
+       }
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                         int argc, const char **argv)
+{
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+
+       if (argc > 2) {
+               printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (argc == 2) {
+               if (strequal(argv[1], "NTLMSSP")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+               } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
+               } else if (strequal(argv[1], "SCHANNEL")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+               } else {
+                       printf("unknown type %s\n", argv[1]);
+                       return NT_STATUS_INVALID_LEVEL;
+               }
+       }
+
+       printf("debuglevel is %d\n", DEBUGLEVEL);
+       return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                         int argc, const char **argv)
+{
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+
+       if (argc > 2) {
+               printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (argc == 2) {
+               if (strequal(argv[1], "NTLMSSP")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+               } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
+               } else if (strequal(argv[1], "SCHANNEL")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+               } else {
+                       printf("unknown type %s\n", argv[1]);
+                       return NT_STATUS_INVALID_LEVEL;
+               }
+       }
+       return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                           int argc, const char **argv)
+{
+       struct cmd_list *tmp;
+
+       if (argc > 2) {
+               printf("Usage: %s timeout\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (argc == 2) {
+               timeout = atoi(argv[1]);
+
+               for (tmp = cmd_list; tmp; tmp = tmp->next) {
+                       
+                       struct cmd_set *tmp_set;
+
+                       for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
+                               if (tmp_set->rpc_pipe == NULL) {
+                                       continue;
+                               }
+
+                               cli_set_timeout(tmp_set->rpc_pipe->cli, timeout);
+                       }
+               }
+       }
+
+       printf("timeout is %d\n", timeout);
+
+       return NT_STATUS_OK;
+}
+
+
+static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                         int argc, const char **argv)
+{
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
+
+       return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                            int argc, const char **argv)
+{
+       d_printf("Setting schannel - sign and seal\n");
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+
+       return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                            int argc, const char **argv)
+{
+       d_printf("Setting schannel - sign only\n");
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+
+       return cmd_set_ss_level();
+}
+
+
 /* Built in rpcclient commands */
 
 static struct cmd_set rpcclient_commands[] = {
 
        { "GENERAL OPTIONS" },
 
-       { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL,     -1,   "Get help on commands", "[command]" },
-       { "?",  RPC_RTYPE_NTSTATUS, cmd_help, NULL,       -1,   "Get help on commands", "[command]" },
-       { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   -1, "Set debug level", "level" },
-       { "list",       RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, "List available commands on <pipe>", "pipe" },
-       { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,   -1,     "Exit program", "" },
-       { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,     -1,   "Exit program", "" },
+       { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL,     -1, NULL,     "Get help on commands", "[command]" },
+       { "?",  RPC_RTYPE_NTSTATUS, cmd_help, NULL,       -1, NULL,     "Get help on commands", "[command]" },
+       { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   -1, NULL, "Set debug level", "level" },
+       { "debug", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   -1,      NULL, "Set debug level", "level" },
+       { "list",       RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, NULL, "List available commands on <pipe>", "pipe" },
+       { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,   -1,     NULL,   "Exit program", "" },
+       { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,     -1,   NULL, "Exit program", "" },
+       { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL,     -1,   NULL, "Force RPC pipe connections to be signed", "" },
+       { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL,     -1,   NULL, "Force RPC pipe connections to be sealed", "" },
+       { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL,     -1, NULL,     "Force RPC pipe connections to be sealed with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
+       { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL,    -1, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
+       { "timeout", RPC_RTYPE_NTSTATUS, cmd_timeout, NULL,       -1, NULL, "Set timeout (in milliseonds) for RPC operations", "" },
+       { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL,     -1, NULL, "Force RPC pipe connections to have no special properties", "" },
 
        { NULL }
 };
 
 static struct cmd_set separator_command[] = {
-       { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL,   -1,     "----------------------" },
+       { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL,   -1, NULL, "----------------------" },
        { NULL }
 };
 
@@ -420,8 +498,10 @@ extern struct cmd_set spoolss_commands[];
 extern struct cmd_set netlogon_commands[];
 extern struct cmd_set srvsvc_commands[];
 extern struct cmd_set dfs_commands[];
-extern struct cmd_set reg_commands[];
 extern struct cmd_set ds_commands[];
+extern struct cmd_set echo_commands[];
+extern struct cmd_set shutdown_commands[];
+extern struct cmd_set test_commands[];
 
 static struct cmd_set *rpcclient_command_list[] = {
        rpcclient_commands,
@@ -432,7 +512,9 @@ static struct cmd_set *rpcclient_command_list[] = {
        netlogon_commands,
        srvsvc_commands,
        dfs_commands,
-       reg_commands,
+       echo_commands,
+       shutdown_commands,
+       test_commands,
        NULL
 };
 
@@ -440,7 +522,7 @@ static void add_command_set(struct cmd_set *cmd_set)
 {
        struct cmd_list *entry;
 
-       if (!(entry = (struct cmd_list *)malloc(sizeof(struct cmd_list)))) {
+       if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
                DEBUG(0, ("out of memory\n"));
                return;
        }
@@ -461,8 +543,8 @@ static NTSTATUS do_cmd(struct cli_state *cli,
                       struct cmd_set *cmd_entry,
                       int argc, char **argv)
 {
-     NTSTATUS ntresult;
-     WERROR wresult;
+       NTSTATUS ntresult;
+       WERROR wresult;
        
        TALLOC_CTX *mem_ctx;
 
@@ -470,38 +552,101 @@ static NTSTATUS do_cmd(struct cli_state *cli,
 
        if (!(mem_ctx = talloc_init("do_cmd"))) {
                DEBUG(0, ("talloc_init() failed\n"));
-               return NT_STATUS_UNSUCCESSFUL;
+               return NT_STATUS_NO_MEMORY;
        }
 
        /* Open pipe */
 
-       if (cmd_entry->pipe_idx != -1)
-               if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) {
-                       DEBUG(0, ("Could not initialize pipe\n"));
-                       return NT_STATUS_UNSUCCESSFUL;
+       if (cmd_entry->pipe_idx != -1 && cmd_entry->rpc_pipe == NULL) {
+               switch (pipe_default_auth_type) {
+                       case PIPE_AUTH_TYPE_NONE:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_noauth(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               &ntresult);
+                               break;
+                       case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               pipe_default_auth_level,
+                                                               lp_workgroup(),
+                                                               cmdline_auth_info.username,
+                                                               cmdline_auth_info.password,
+                                                               &ntresult);
+                               break;
+                       case PIPE_AUTH_TYPE_NTLMSSP:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_ntlmssp(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               pipe_default_auth_level,
+                                                               lp_workgroup(),
+                                                               cmdline_auth_info.username,
+                                                               cmdline_auth_info.password,
+                                                               &ntresult);
+                               break;
+                       case PIPE_AUTH_TYPE_SCHANNEL:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_schannel(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               pipe_default_auth_level,
+                                                               lp_workgroup(),
+                                                               &ntresult);
+                               break;
+                       default:
+                               DEBUG(0, ("Could not initialise %s. Invalid auth type %u\n",
+                                       cli_get_pipe_name(cmd_entry->pipe_idx),
+                                       pipe_default_auth_type ));
+                               return NT_STATUS_UNSUCCESSFUL;
+               }
+               if (!cmd_entry->rpc_pipe) {
+                       DEBUG(0, ("Could not initialise %s. Error was %s\n",
+                               cli_get_pipe_name(cmd_entry->pipe_idx),
+                               nt_errstr(ntresult) ));
+                       return ntresult;
+               }
+
+               if (cmd_entry->pipe_idx == PI_NETLOGON) {
+                       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+                       uint32 sec_channel_type;
+                       uchar trust_password[16];
+       
+                       if (!secrets_fetch_trust_account_password(lp_workgroup(),
+                                                       trust_password,
+                                                       NULL, &sec_channel_type)) {
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
+               
+                       ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe,
+                                               cli->desthost,   /* server name */
+                                               lp_workgroup(),  /* domain */
+                                               global_myname(), /* client name */
+                                               global_myname(), /* machine account name */
+                                               trust_password,
+                                               sec_channel_type,
+                                               &neg_flags);
+
+                       if (!NT_STATUS_IS_OK(ntresult)) {
+                               DEBUG(0, ("Could not initialise credentials for %s.\n",
+                                       cli_get_pipe_name(cmd_entry->pipe_idx)));
+                               return ntresult;
+                       }
                }
+       }
 
-     /* Run command */
-
-     if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
-          ntresult = cmd_entry->ntfn(cli, mem_ctx, argc, (const char **) argv);
-          if (!NT_STATUS_IS_OK(ntresult)) {
-              printf("result was %s\n", nt_errstr(ntresult));
-          }
-     } else {
-          wresult = cmd_entry->wfn( cli, mem_ctx, argc, (const char **) argv);
-          /* print out the DOS error */
-          if (!W_ERROR_IS_OK(wresult)) {
-                  printf( "result was %s\n", dos_errstr(wresult));
-          }
-          ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
-     }
-            
+       /* Run command */
 
-       /* Cleanup */
+       if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
+               ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
+               if (!NT_STATUS_IS_OK(ntresult)) {
+                       printf("result was %s\n", nt_errstr(ntresult));
+               }
+       } else {
+               wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
+               /* print out the DOS error */
+               if (!W_ERROR_IS_OK(wresult)) {
+                       printf( "result was %s\n", dos_errstr(wresult));
+               }
+               ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
+       }
 
-       if (cmd_entry->pipe_idx != -1)
-               cli_nt_session_close(cli);
+       /* Cleanup */
 
        talloc_destroy(mem_ctx);
 
@@ -559,13 +704,11 @@ out_free:
        }
 */
 
-       if (argv) {
-               /* NOTE: popt allocates the whole argv, including the
-                * strings, as a single block.  So a single free is
-                * enough to release it -- we don't free the
-                * individual strings.  rtfm. */
-               free(argv);
-       }
+       /* NOTE: popt allocates the whole argv, including the
+        * strings, as a single block.  So a single free is
+        * enough to release it -- we don't free the
+        * individual strings.  rtfm. */
+       free(argv);
        
        return result;
 }
@@ -575,47 +718,41 @@ out_free:
 
  int main(int argc, char *argv[])
 {
-       static int              got_pass = 0;
-       BOOL                    interactive = True;
        int                     opt;
-       static char             *cmdstr = "";
+       static char             *cmdstr = NULL;
        const char *server;
        struct cli_state        *cli;
-       fstring                 password="",
-                               username="",
-               domain="";
-       static char             *opt_authfile=NULL,
-                               *opt_username=NULL,
-                               *opt_domain=NULL,
-                               *opt_logfile=NULL,
-                               *opt_ipaddr=NULL;
-       pstring                 logfile;
+       static char             *opt_ipaddr=NULL;
        struct cmd_set          **cmd_set;
        struct in_addr          server_ip;
        NTSTATUS                nt_status;
+       static int              opt_port = 0;
+       fstring new_workgroup;
 
        /* make sure the vars that get altered (4th field) are in
           a fixed location or certain compilers complain */
        poptContext pc;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
-               {"authfile",    'A', POPT_ARG_STRING,   &opt_authfile, 'A', "File containing user credentials", "AUTHFILE"},
-               {"nopass",      'N', POPT_ARG_NONE,     &got_pass, 'N', "Don't ask for a password"},
-               {"user", 'U', POPT_ARG_STRING,  &opt_username, 'U', "Set the network username", "USER"},
-               {"workgroup", 'W', POPT_ARG_STRING,     &opt_domain, 'W', "Set the domain name for user account", "DOMAIN"},
                {"command",     'c', POPT_ARG_STRING,   &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
-               {"logfile",     'l', POPT_ARG_STRING,   &opt_logfile, 'l', "Logfile to use instead of stdout", "LOGFILE" },
                {"dest-ip", 'I', POPT_ARG_STRING,   &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
-               { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
-               { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
-               { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
-               { NULL }
+               {"port", 'p', POPT_ARG_INT,   &opt_port, 'p', "Specify port number", "PORT"},
+               POPT_COMMON_SAMBA
+               POPT_COMMON_CONNECTION
+               POPT_COMMON_CREDENTIALS
+               POPT_TABLEEND
        };
 
+       load_case_tables();
+
        ZERO_STRUCT(server_ip);
 
        setlinebuf(stdout);
 
+       /* the following functions are part of the Samba debugging
+          facilities.  See lib/debug.c */
+       setup_logging("rpcclient", True);
+       
        /* Parse options */
 
        pc = poptGetContext("rpcclient", argc, (const char **) argv,
@@ -628,43 +765,13 @@ out_free:
        
        while((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
-               case 'A':
-                       /* only get the username, password, and domain from the file */
-                       read_authfile (opt_authfile, username, password, domain);
-                       if (strlen (password))
-                               got_pass = 1;
-                       break;
-                       
-               case 'l':
-                       slprintf(logfile, sizeof(logfile) - 1, "%s.client", 
-                                opt_logfile);
-                       lp_set_logfile(logfile);
-                       interactive = False;
-                       break;
-                       
-               case 'U': {
-                       char *lp;
-
-                       fstrcpy(username,opt_username);
 
-                       if ((lp=strchr_m(username,'%'))) {
-                               *lp = 0;
-                               fstrcpy(password,lp+1);
-                               got_pass = 1;
-                               memset(strchr_m(opt_username,'%') + 1, 'X',
-                                      strlen(password));
-                       }
-                       break;
-               }
                case 'I':
                        if ( (server_ip.s_addr=inet_addr(opt_ipaddr)) == INADDR_NONE ) {
                                fprintf(stderr, "%s not a valid IP address\n",
                                        opt_ipaddr);
                                return 1;
                        }
-               case 'W':
-                       fstrcpy(domain, opt_domain);
-                       break;
                }
        }
 
@@ -680,52 +787,66 @@ out_free:
 
        poptFreeContext(pc);
 
-       /* the following functions are part of the Samba debugging
-          facilities.  See lib/debug.c */
-       setup_logging("rpcclient", interactive);
-       if (!interactive) 
-               reopen_logs();
+       load_interfaces();
+
+       if (!init_names())
+               return 1;
+
+       /* save the workgroup...
+       
+          FIXME!! do we need to do this for other options as well 
+          (or maybe a generic way to keep lp_load() from overwriting 
+          everything)?  */
        
+       fstrcpy( new_workgroup, lp_workgroup() );
+
        /* Load smb.conf file */
 
-       if (!lp_load(dyn_CONFIGFILE,True,False,False))
+       if (!lp_load(dyn_CONFIGFILE,True,False,False,True))
                fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
 
-       load_interfaces();
-
-       if (!init_names())
-               return 1;
+       if ( strlen(new_workgroup) != 0 )
+               set_global_myworkgroup( new_workgroup );
 
        /*
         * Get password
         * from stdin if necessary
         */
 
-       if (!got_pass) {
+       if (!cmdline_auth_info.got_pass) {
                char *pass = getpass("Password:");
                if (pass) {
-                       fstrcpy(password, pass);
+                       pstrcpy(cmdline_auth_info.password, pass);
                }
        }
        
-       if (!strlen(username) && !got_pass)
-               get_username(username);
-               
+       if ((server[0] == '/' && server[1] == '/') ||
+                       (server[0] == '\\' && server[1] ==  '\\')) {
+               server += 2;
+       }
+
        nt_status = cli_full_connection(&cli, global_myname(), server, 
-                                       opt_ipaddr ? &server_ip : NULL, 0,
+                                       opt_ipaddr ? &server_ip : NULL, opt_port,
                                        "IPC$", "IPC",  
-                                       username, domain,
-                                       password, 0, NULL);
+                                       cmdline_auth_info.username, 
+                                       lp_workgroup(),
+                                       cmdline_auth_info.password, 
+                                       cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
+                                       cmdline_auth_info.signing_state,NULL);
        
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("Cannot connect to server.  Error was %s\n", nt_errstr(nt_status)));
                return 1;
        }
 
-       memset(password,'X',sizeof(password));
+#if 0  /* COMMENT OUT FOR TESTING */
+       memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
+#endif
 
        /* Load command lists */
 
+       timeout = cli_set_timeout(cli, 10000);
+
        cmd_set = rpcclient_command_list;
 
        while(*cmd_set) {
@@ -737,16 +858,19 @@ out_free:
        fetch_machine_sid(cli);
  
        /* Do anything specified with -c */
-        if (cmdstr[0]) {
+        if (cmdstr && cmdstr[0]) {
                 char    *cmd;
                 char    *p = cmdstr;
+               int result = 0;
  
                 while((cmd=next_command(&p)) != NULL) {
-                        process_cmd(cli, cmd);
+                        NTSTATUS cmd_result = process_cmd(cli, cmd);
+                       SAFE_FREE(cmd);
+                       result = NT_STATUS_IS_ERR(cmd_result);
                 }
                
                cli_shutdown(cli);
-                return 0;
+                return result;
         }
 
        /* Loop around accepting commands */