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 "rpcclient.h" 24#include "../libcli/auth/libcli_auth.h" 25#include "../librpc/gen_ndr/cli_lsa.h" 26 27DOM_SID domain_sid; 28 29static enum pipe_auth_type pipe_default_auth_type = PIPE_AUTH_TYPE_NONE; 30static enum dcerpc_AuthLevel pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE; 31static unsigned int timeout = 0; 32static enum dcerpc_transport_t default_transport = NCACN_NP; 33 34struct user_auth_info *rpcclient_auth_info; 35 36/* List to hold groups of commands. 37 * 38 * Commands are defined in a list of arrays: arrays are easy to 39 * statically declare, and lists are easier to dynamically extend. 40 */ 41 42static struct cmd_list { 43 struct cmd_list *prev, *next; 44 struct cmd_set *cmd_set; 45} *cmd_list; 46 47/**************************************************************************** 48handle completion of commands for readline 49****************************************************************************/ 50static char **completion_fn(const char *text, int start, int end) 51{ 52#define MAX_COMPLETIONS 1000 53 char **matches; 54 int i, count=0; 55 struct cmd_list *commands = cmd_list; 56 57#if 0 /* JERRY */ 58 /* FIXME!!! -- what to do when completing argument? */ 59 /* for words not at the start of the line fallback 60 to filename completion */ 61 if (start) 62 return NULL; 63#endif 64 65 /* make sure we have a list of valid commands */ 66 if (!commands) { 67 return NULL; 68 } 69 70 matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS); 71 if (!matches) { 72 return NULL; 73 } 74 75 matches[count++] = SMB_STRDUP(text); 76 if (!matches[0]) { 77 SAFE_FREE(matches); 78 return NULL; 79 } 80 81 while (commands && count < MAX_COMPLETIONS-1) { 82 if (!commands->cmd_set) { 83 break; 84 } 85 86 for (i=0; commands->cmd_set[i].name; i++) { 87 if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) && 88 (( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS && 89 commands->cmd_set[i].ntfn ) || 90 ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR && 91 commands->cmd_set[i].wfn))) { 92 matches[count] = SMB_STRDUP(commands->cmd_set[i].name); 93 if (!matches[count]) { 94 for (i = 0; i < count; i++) { 95 SAFE_FREE(matches[count]); 96 } 97 SAFE_FREE(matches); 98 return NULL; 99 } 100 count++; 101 } 102 } 103 commands = commands->next; 104 105 } 106 107 if (count == 2) { 108 SAFE_FREE(matches[0]); 109 matches[0] = SMB_STRDUP(matches[1]); 110 } 111 matches[count] = NULL; 112 return matches; 113} 114 115static char *next_command (char **cmdstr) 116{ 117 char *command; 118 char *p; 119 120 if (!cmdstr || !(*cmdstr)) 121 return NULL; 122 123 p = strchr_m(*cmdstr, ';'); 124 if (p) 125 *p = '\0'; 126 command = SMB_STRDUP(*cmdstr); 127 if (p) 128 *cmdstr = p + 1; 129 else 130 *cmdstr = NULL; 131 132 return command; 133} 134 135/* Fetch the SID for this computer */ 136 137static void fetch_machine_sid(struct cli_state *cli) 138{ 139 struct policy_handle pol; 140 NTSTATUS result = NT_STATUS_OK; 141 static bool got_domain_sid; 142 TALLOC_CTX *mem_ctx; 143 struct rpc_pipe_client *lsapipe = NULL; 144 union lsa_PolicyInformation *info = NULL; 145 146 if (got_domain_sid) return; 147 148 if (!(mem_ctx=talloc_init("fetch_machine_sid"))) { 149 DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n")); 150 goto error; 151 } 152 153 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, 154 &lsapipe); 155 if (!NT_STATUS_IS_OK(result)) { 156 fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) ); 157 goto error; 158 } 159 160 result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True, 161 SEC_FLAG_MAXIMUM_ALLOWED, 162 &pol); 163 if (!NT_STATUS_IS_OK(result)) { 164 goto error; 165 } 166 167 result = rpccli_lsa_QueryInfoPolicy(lsapipe, mem_ctx, 168 &pol, 169 LSA_POLICY_INFO_ACCOUNT_DOMAIN, 170 &info); 171 if (!NT_STATUS_IS_OK(result)) { 172 goto error; 173 } 174 175 got_domain_sid = True; 176 sid_copy(&domain_sid, info->account_domain.sid); 177 178 rpccli_lsa_Close(lsapipe, mem_ctx, &pol); 179 TALLOC_FREE(lsapipe); 180 talloc_destroy(mem_ctx); 181 182 return; 183 184 error: 185 186 if (lsapipe) { 187 TALLOC_FREE(lsapipe); 188 } 189 190 fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain); 191 192 if (!NT_STATUS_IS_OK(result)) { 193 fprintf(stderr, "error: %s\n", nt_errstr(result)); 194 } 195 196 exit(1); 197} 198 199/* List the available commands on a given pipe */ 200 201static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 202 int argc, const char **argv) 203{ 204 struct cmd_list *tmp; 205 struct cmd_set *tmp_set; 206 int i; 207 208 /* Usage */ 209 210 if (argc != 2) { 211 printf("Usage: %s <pipe>\n", argv[0]); 212 return NT_STATUS_OK; 213 } 214 215 /* Help on one command */ 216 217 for (tmp = cmd_list; tmp; tmp = tmp->next) 218 { 219 tmp_set = tmp->cmd_set; 220 221 if (!StrCaseCmp(argv[1], tmp_set->name)) 222 { 223 printf("Available commands on the %s pipe:\n\n", tmp_set->name); 224 225 i = 0; 226 tmp_set++; 227 while(tmp_set->name) { 228 printf("%30s", tmp_set->name); 229 tmp_set++; 230 i++; 231 if (i%3 == 0) 232 printf("\n"); 233 } 234 235 /* drop out of the loop */ 236 break; 237 } 238 } 239 printf("\n\n"); 240 241 return NT_STATUS_OK; 242} 243 244/* Display help on commands */ 245 246static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 247 int argc, const char **argv) 248{ 249 struct cmd_list *tmp; 250 struct cmd_set *tmp_set; 251 252 /* Usage */ 253 254 if (argc > 2) { 255 printf("Usage: %s [command]\n", argv[0]); 256 return NT_STATUS_OK; 257 } 258 259 /* Help on one command */ 260 261 if (argc == 2) { 262 for (tmp = cmd_list; tmp; tmp = tmp->next) { 263 264 tmp_set = tmp->cmd_set; 265 266 while(tmp_set->name) { 267 if (strequal(argv[1], tmp_set->name)) { 268 if (tmp_set->usage && 269 tmp_set->usage[0]) 270 printf("%s\n", tmp_set->usage); 271 else 272 printf("No help for %s\n", tmp_set->name); 273 274 return NT_STATUS_OK; 275 } 276 277 tmp_set++; 278 } 279 } 280 281 printf("No such command: %s\n", argv[1]); 282 return NT_STATUS_OK; 283 } 284 285 /* List all commands */ 286 287 for (tmp = cmd_list; tmp; tmp = tmp->next) { 288 289 tmp_set = tmp->cmd_set; 290 291 while(tmp_set->name) { 292 293 printf("%15s\t\t%s\n", tmp_set->name, 294 tmp_set->description ? tmp_set->description: 295 ""); 296 297 tmp_set++; 298 } 299 } 300 301 return NT_STATUS_OK; 302} 303 304/* Change the debug level */ 305 306static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 307 int argc, const char **argv) 308{ 309 if (argc > 2) { 310 printf("Usage: %s [debuglevel]\n", argv[0]); 311 return NT_STATUS_OK; 312 } 313 314 if (argc == 2) { 315 DEBUGLEVEL = atoi(argv[1]); 316 } 317 318 printf("debuglevel is %d\n", DEBUGLEVEL); 319 320 return NT_STATUS_OK; 321} 322 323static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 324 int argc, const char **argv) 325{ 326 exit(0); 327 return NT_STATUS_OK; /* NOTREACHED */ 328} 329 330static NTSTATUS cmd_set_ss_level(void) 331{ 332 struct cmd_list *tmp; 333 334 /* Close any existing connections not at this level. */ 335 336 for (tmp = cmd_list; tmp; tmp = tmp->next) { 337 struct cmd_set *tmp_set; 338 339 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) { 340 if (tmp_set->rpc_pipe == NULL) { 341 continue; 342 } 343 344 if ((tmp_set->rpc_pipe->auth->auth_type 345 != pipe_default_auth_type) 346 || (tmp_set->rpc_pipe->auth->auth_level 347 != pipe_default_auth_level)) { 348 TALLOC_FREE(tmp_set->rpc_pipe); 349 tmp_set->rpc_pipe = NULL; 350 } 351 } 352 } 353 return NT_STATUS_OK; 354} 355 356static NTSTATUS cmd_set_transport(void) 357{ 358 struct cmd_list *tmp; 359 360 /* Close any existing connections not at this level. */ 361 362 for (tmp = cmd_list; tmp; tmp = tmp->next) { 363 struct cmd_set *tmp_set; 364 365 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) { 366 if (tmp_set->rpc_pipe == NULL) { 367 continue; 368 } 369 370 if (tmp_set->rpc_pipe->transport->transport != default_transport) { 371 TALLOC_FREE(tmp_set->rpc_pipe); 372 tmp_set->rpc_pipe = NULL; 373 } 374 } 375 } 376 return NT_STATUS_OK; 377} 378 379static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 380 int argc, const char **argv) 381{ 382 const char *type = "NTLMSSP"; 383 384 pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; 385 pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; 386 387 if (argc > 2) { 388 printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]); 389 return NT_STATUS_OK; 390 } 391 392 if (argc == 2) { 393 type = argv[1]; 394 if (strequal(type, "NTLMSSP")) { 395 pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; 396 } else if (strequal(type, "NTLMSSP_SPNEGO")) { 397 pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; 398 } else if (strequal(type, "SCHANNEL")) { 399 pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; 400 } else { 401 printf("unknown type %s\n", type); 402 return NT_STATUS_INVALID_LEVEL; 403 } 404 } 405 406 d_printf("Setting %s - sign\n", type); 407 408 return cmd_set_ss_level(); 409} 410 411static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 412 int argc, const char **argv) 413{ 414 const char *type = "NTLMSSP"; 415 416 pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY; 417 pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; 418 419 if (argc > 2) { 420 printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]); 421 return NT_STATUS_OK; 422 } 423 424 if (argc == 2) { 425 type = argv[1]; 426 if (strequal(type, "NTLMSSP")) { 427 pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; 428 } else if (strequal(type, "NTLMSSP_SPNEGO")) { 429 pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; 430 } else if (strequal(type, "SCHANNEL")) { 431 pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; 432 } else { 433 printf("unknown type %s\n", type); 434 return NT_STATUS_INVALID_LEVEL; 435 } 436 } 437 438 d_printf("Setting %s - sign and seal\n", type); 439 440 return cmd_set_ss_level(); 441} 442 443static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 444 int argc, const char **argv) 445{ 446 struct cmd_list *tmp; 447 448 if (argc > 2) { 449 printf("Usage: %s timeout\n", argv[0]); 450 return NT_STATUS_OK; 451 } 452 453 if (argc == 2) { 454 timeout = atoi(argv[1]); 455 456 for (tmp = cmd_list; tmp; tmp = tmp->next) { 457 458 struct cmd_set *tmp_set; 459 460 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) { 461 if (tmp_set->rpc_pipe == NULL) { 462 continue; 463 } 464 465 rpccli_set_timeout(tmp_set->rpc_pipe, timeout); 466 } 467 } 468 } 469 470 printf("timeout is %d\n", timeout); 471 472 return NT_STATUS_OK; 473} 474 475 476static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 477 int argc, const char **argv) 478{ 479 pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE; 480 pipe_default_auth_type = PIPE_AUTH_TYPE_NONE; 481 482 return cmd_set_ss_level(); 483} 484 485static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 486 int argc, const char **argv) 487{ 488 d_printf("Setting schannel - sign and seal\n"); 489 pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY; 490 pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; 491 492 return cmd_set_ss_level(); 493} 494 495static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 496 int argc, const char **argv) 497{ 498 d_printf("Setting schannel - sign only\n"); 499 pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; 500 pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; 501 502 return cmd_set_ss_level(); 503} 504 505static NTSTATUS cmd_choose_transport(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 506 int argc, const char **argv) 507{ 508 NTSTATUS status; 509 510 if (argc != 2) { 511 printf("Usage: %s [NCACN_NP|NCACN_IP_TCP]\n", argv[0]); 512 return NT_STATUS_OK; 513 } 514 515 if (strequal(argv[1], "NCACN_NP")) { 516 default_transport = NCACN_NP; 517 } else if (strequal(argv[1], "NCACN_IP_TCP")) { 518 default_transport = NCACN_IP_TCP; 519 } else { 520 printf("transport type: %s unknown or not supported\n", argv[1]); 521 return NT_STATUS_NOT_SUPPORTED; 522 } 523 524 status = cmd_set_transport(); 525 if (!NT_STATUS_IS_OK(status)) { 526 return status; 527 } 528 529 printf("default transport is now: %s\n", argv[1]); 530 531 return NT_STATUS_OK; 532} 533 534/* Built in rpcclient commands */ 535 536static struct cmd_set rpcclient_commands[] = { 537 538 { "GENERAL OPTIONS" }, 539 540 { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL, NULL, NULL, "Get help on commands", "[command]" }, 541 { "?", RPC_RTYPE_NTSTATUS, cmd_help, NULL, NULL, NULL, "Get help on commands", "[command]" }, 542 { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL, NULL, NULL, "Set debug level", "level" }, 543 { "debug", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL, NULL, NULL, "Set debug level", "level" }, 544 { "list", RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, NULL, NULL, "List available commands on <pipe>", "pipe" }, 545 { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, NULL, NULL, "Exit program", "" }, 546 { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, NULL, NULL, "Exit program", "" }, 547 { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL, NULL, NULL, "Force RPC pipe connections to be signed", "" }, 548 { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL, NULL, NULL, "Force RPC pipe connections to be sealed", "" }, 549 { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL, NULL, NULL, "Force RPC pipe connections to be sealed with 'schannel'. Assumes valid machine account to this domain controller.", "" }, 550 { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL, NULL, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'. Assumes valid machine account to this domain controller.", "" }, 551 { "timeout", RPC_RTYPE_NTSTATUS, cmd_timeout, NULL, NULL, NULL, "Set timeout (in milliseonds) for RPC operations", "" }, 552 { "transport", RPC_RTYPE_NTSTATUS, cmd_choose_transport, NULL, NULL, NULL, "Choose ncacn transport for RPC operations", "" }, 553 { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL, NULL, NULL, "Force RPC pipe connections to have no special properties", "" }, 554 555 { NULL } 556}; 557 558static struct cmd_set separator_command[] = { 559 { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL, NULL, NULL, "----------------------" }, 560 { NULL } 561}; 562 563 564/* Various pipe commands */ 565 566extern struct cmd_set lsarpc_commands[]; 567extern struct cmd_set samr_commands[]; 568extern struct cmd_set spoolss_commands[]; 569extern struct cmd_set netlogon_commands[]; 570extern struct cmd_set srvsvc_commands[]; 571extern struct cmd_set dfs_commands[]; 572extern struct cmd_set ds_commands[]; 573extern struct cmd_set echo_commands[]; 574extern struct cmd_set epmapper_commands[]; 575extern struct cmd_set shutdown_commands[]; 576extern struct cmd_set test_commands[]; 577extern struct cmd_set wkssvc_commands[]; 578extern struct cmd_set ntsvcs_commands[]; 579extern struct cmd_set drsuapi_commands[]; 580extern struct cmd_set eventlog_commands[]; 581 582static struct cmd_set *rpcclient_command_list[] = { 583 rpcclient_commands, 584 lsarpc_commands, 585 ds_commands, 586 samr_commands, 587 spoolss_commands, 588 netlogon_commands, 589 srvsvc_commands, 590 dfs_commands, 591 echo_commands, 592 epmapper_commands, 593 shutdown_commands, 594 test_commands, 595 wkssvc_commands, 596 ntsvcs_commands, 597 drsuapi_commands, 598 eventlog_commands, 599 NULL 600}; 601 602static void add_command_set(struct cmd_set *cmd_set) 603{ 604 struct cmd_list *entry; 605 606 if (!(entry = SMB_MALLOC_P(struct cmd_list))) { 607 DEBUG(0, ("out of memory\n")); 608 return; 609 } 610 611 ZERO_STRUCTP(entry); 612 613 entry->cmd_set = cmd_set; 614 DLIST_ADD(cmd_list, entry); 615} 616 617 618/** 619 * Call an rpcclient function, passing an argv array. 620 * 621 * @param cmd Command to run, as a single string. 622 **/ 623static NTSTATUS do_cmd(struct cli_state *cli, 624 struct user_auth_info *auth_info, 625 struct cmd_set *cmd_entry, 626 struct dcerpc_binding *binding, 627 int argc, char **argv) 628{ 629 NTSTATUS ntresult; 630 WERROR wresult; 631 632 TALLOC_CTX *mem_ctx; 633 634 /* Create mem_ctx */ 635 636 if (!(mem_ctx = talloc_init("do_cmd"))) { 637 DEBUG(0, ("talloc_init() failed\n")); 638 return NT_STATUS_NO_MEMORY; 639 } 640 641 /* Open pipe */ 642 643 if ((cmd_entry->interface != NULL) && (cmd_entry->rpc_pipe == NULL)) { 644 switch (pipe_default_auth_type) { 645 case PIPE_AUTH_TYPE_NONE: 646 ntresult = cli_rpc_pipe_open_noauth_transport( 647 cli, default_transport, 648 cmd_entry->interface, 649 &cmd_entry->rpc_pipe); 650 break; 651 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: 652 ntresult = cli_rpc_pipe_open_spnego_ntlmssp( 653 cli, cmd_entry->interface, 654 default_transport, 655 pipe_default_auth_level, 656 get_cmdline_auth_info_domain(auth_info), 657 get_cmdline_auth_info_username(auth_info), 658 get_cmdline_auth_info_password(auth_info), 659 &cmd_entry->rpc_pipe); 660 break; 661 case PIPE_AUTH_TYPE_NTLMSSP: 662 ntresult = cli_rpc_pipe_open_ntlmssp( 663 cli, cmd_entry->interface, 664 default_transport, 665 pipe_default_auth_level, 666 get_cmdline_auth_info_domain(auth_info), 667 get_cmdline_auth_info_username(auth_info), 668 get_cmdline_auth_info_password(auth_info), 669 &cmd_entry->rpc_pipe); 670 break; 671 case PIPE_AUTH_TYPE_SCHANNEL: 672 ntresult = cli_rpc_pipe_open_schannel( 673 cli, cmd_entry->interface, 674 default_transport, 675 pipe_default_auth_level, 676 get_cmdline_auth_info_domain(auth_info), 677 &cmd_entry->rpc_pipe); 678 break; 679 default: 680 DEBUG(0, ("Could not initialise %s. Invalid " 681 "auth type %u\n", 682 get_pipe_name_from_syntax( 683 talloc_tos(), 684 cmd_entry->interface), 685 pipe_default_auth_type )); 686 return NT_STATUS_UNSUCCESSFUL; 687 } 688 if (!NT_STATUS_IS_OK(ntresult)) { 689 DEBUG(0, ("Could not initialise %s. Error was %s\n", 690 get_pipe_name_from_syntax( 691 talloc_tos(), cmd_entry->interface), 692 nt_errstr(ntresult) )); 693 return ntresult; 694 } 695 696 if (ndr_syntax_id_equal(cmd_entry->interface, 697 &ndr_table_netlogon.syntax_id)) { 698 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; 699 enum netr_SchannelType sec_channel_type; 700 uchar trust_password[16]; 701 const char *machine_account; 702 703 if (!get_trust_pw_hash(get_cmdline_auth_info_domain(auth_info), 704 trust_password, &machine_account, 705 &sec_channel_type)) 706 { 707 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; 708 } 709 710 ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe, 711 cli->desthost, /* server name */ 712 get_cmdline_auth_info_domain(auth_info), /* domain */ 713 global_myname(), /* client name */ 714 machine_account, /* machine account name */ 715 trust_password, 716 sec_channel_type, 717 &neg_flags); 718 719 if (!NT_STATUS_IS_OK(ntresult)) { 720 DEBUG(0, ("Could not initialise credentials for %s.\n", 721 get_pipe_name_from_syntax( 722 talloc_tos(), 723 cmd_entry->interface))); 724 return ntresult; 725 } 726 } 727 } 728 729 /* Run command */ 730 731 if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { 732 ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv); 733 if (!NT_STATUS_IS_OK(ntresult)) { 734 printf("result was %s\n", nt_errstr(ntresult)); 735 } 736 } else { 737 wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv); 738 /* print out the DOS error */ 739 if (!W_ERROR_IS_OK(wresult)) { 740 printf( "result was %s\n", win_errstr(wresult)); 741 } 742 ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL; 743 } 744 745 /* Cleanup */ 746 747 talloc_destroy(mem_ctx); 748 749 return ntresult; 750} 751 752 753/** 754 * Process a command entered at the prompt or as part of -c 755 * 756 * @returns The NTSTATUS from running the command. 757 **/ 758static NTSTATUS process_cmd(struct user_auth_info *auth_info, 759 struct cli_state *cli, 760 struct dcerpc_binding *binding, 761 char *cmd) 762{ 763 struct cmd_list *temp_list; 764 NTSTATUS result = NT_STATUS_OK; 765 int ret; 766 int argc; 767 char **argv = NULL; 768 769 if ((ret = poptParseArgvString(cmd, &argc, (const char ***) &argv)) != 0) { 770 fprintf(stderr, "rpcclient: %s\n", poptStrerror(ret)); 771 return NT_STATUS_UNSUCCESSFUL; 772 } 773 774 775 /* Walk through a dlist of arrays of commands. */ 776 for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) { 777 struct cmd_set *temp_set = temp_list->cmd_set; 778 779 while (temp_set->name) { 780 if (strequal(argv[0], temp_set->name)) { 781 if (!(temp_set->returntype == RPC_RTYPE_NTSTATUS && temp_set->ntfn ) && 782 !(temp_set->returntype == RPC_RTYPE_WERROR && temp_set->wfn )) { 783 fprintf (stderr, "Invalid command\n"); 784 goto out_free; 785 } 786 787 result = do_cmd(cli, auth_info, temp_set, 788 binding, argc, argv); 789 790 goto out_free; 791 } 792 temp_set++; 793 } 794 } 795 796 if (argv[0]) { 797 printf("command not found: %s\n", argv[0]); 798 } 799 800out_free: 801/* moved to do_cmd() 802 if (!NT_STATUS_IS_OK(result)) { 803 printf("result was %s\n", nt_errstr(result)); 804 } 805*/ 806 807 /* NOTE: popt allocates the whole argv, including the 808 * strings, as a single block. So a single free is 809 * enough to release it -- we don't free the 810 * individual strings. rtfm. */ 811 free(argv); 812 813 return result; 814} 815 816 817/* Main function */ 818 819 int main(int argc, char *argv[]) 820{ 821 int opt; 822 static char *cmdstr = NULL; 823 const char *server; 824 struct cli_state *cli = NULL; 825 static char *opt_ipaddr=NULL; 826 struct cmd_set **cmd_set; 827 struct sockaddr_storage server_ss; 828 NTSTATUS nt_status; 829 static int opt_port = 0; 830 fstring new_workgroup; 831 int result = 0; 832 TALLOC_CTX *frame = talloc_stackframe(); 833 uint32_t flags = 0; 834 struct dcerpc_binding *binding = NULL; 835 const char *binding_string = NULL; 836 char *user, *domain, *q; 837 838 /* make sure the vars that get altered (4th field) are in 839 a fixed location or certain compilers complain */ 840 poptContext pc; 841 struct poptOption long_options[] = { 842 POPT_AUTOHELP 843 {"command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"}, 844 {"dest-ip", 'I', POPT_ARG_STRING, &opt_ipaddr, 'I', "Specify destination IP address", "IP"}, 845 {"port", 'p', POPT_ARG_INT, &opt_port, 'p', "Specify port number", "PORT"}, 846 POPT_COMMON_SAMBA 847 POPT_COMMON_CONNECTION 848 POPT_COMMON_CREDENTIALS 849 POPT_TABLEEND 850 }; 851 852 load_case_tables(); 853 854 zero_sockaddr(&server_ss); 855 856 setlinebuf(stdout); 857 858 /* the following functions are part of the Samba debugging 859 facilities. See lib/debug.c */ 860 setup_logging("rpcclient", True); 861 862 rpcclient_auth_info = user_auth_info_init(frame); 863 if (rpcclient_auth_info == NULL) { 864 exit(1); 865 } 866 popt_common_set_auth_info(rpcclient_auth_info); 867 868 /* Parse options */ 869 870 pc = poptGetContext("rpcclient", argc, (const char **) argv, 871 long_options, 0); 872 873 if (argc == 1) { 874 poptPrintHelp(pc, stderr, 0); 875 goto done; 876 } 877 878 while((opt = poptGetNextOpt(pc)) != -1) { 879 switch (opt) { 880 881 case 'I': 882 if (!interpret_string_addr(&server_ss, 883 opt_ipaddr, 884 AI_NUMERICHOST)) { 885 fprintf(stderr, "%s not a valid IP address\n", 886 opt_ipaddr); 887 result = 1; 888 goto done; 889 } 890 } 891 } 892 893 /* Get server as remaining unparsed argument. Print usage if more 894 than one unparsed argument is present. */ 895 896 server = poptGetArg(pc); 897 898 if (!server || poptGetArg(pc)) { 899 poptPrintHelp(pc, stderr, 0); 900 result = 1; 901 goto done; 902 } 903 904 poptFreeContext(pc); 905 906 load_interfaces(); 907 908 if (!init_names()) { 909 result = 1; 910 goto done; 911 } 912 913 /* save the workgroup... 914 915 FIXME!! do we need to do this for other options as well 916 (or maybe a generic way to keep lp_load() from overwriting 917 everything)? */ 918 919 fstrcpy( new_workgroup, lp_workgroup() ); 920 921 /* Load smb.conf file */ 922 923 if (!lp_load(get_dyn_CONFIGFILE(),True,False,False,True)) 924 fprintf(stderr, "Can't load %s\n", get_dyn_CONFIGFILE()); 925 926 if ( strlen(new_workgroup) != 0 ) 927 set_global_myworkgroup( new_workgroup ); 928 929 /* 930 * Get password 931 * from stdin if necessary 932 */ 933 934 if (get_cmdline_auth_info_use_machine_account(rpcclient_auth_info) && 935 !set_cmdline_auth_info_machine_account_creds(rpcclient_auth_info)) { 936 result = 1; 937 goto done; 938 } 939 940 set_cmdline_auth_info_getpass(rpcclient_auth_info); 941 942 if ((server[0] == '/' && server[1] == '/') || 943 (server[0] == '\\' && server[1] == '\\')) { 944 server += 2; 945 } 946 947 nt_status = dcerpc_parse_binding(frame, server, &binding); 948 949 if (!NT_STATUS_IS_OK(nt_status)) { 950 951 binding_string = talloc_asprintf(frame, "ncacn_np:%s", 952 strip_hostname(server)); 953 if (!binding_string) { 954 result = 1; 955 goto done; 956 } 957 958 nt_status = dcerpc_parse_binding(frame, binding_string, &binding); 959 if (!NT_STATUS_IS_OK(nt_status)) { 960 result = -1; 961 goto done; 962 } 963 } 964 965 if (binding->transport == NCA_UNKNOWN) { 966 binding->transport = NCACN_NP; 967 } 968 969 if (binding->flags & DCERPC_SIGN) { 970 pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; 971 pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; 972 } 973 if (binding->flags & DCERPC_SEAL) { 974 pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY; 975 pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; 976 } 977 if (binding->flags & DCERPC_AUTH_SPNEGO) { 978 pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; 979 } 980 if (binding->flags & DCERPC_AUTH_NTLM) { 981 pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; 982 } 983 if (binding->flags & DCERPC_AUTH_KRB5) { 984 pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_KRB5; 985 } 986 987 if (get_cmdline_auth_info_use_kerberos(rpcclient_auth_info)) { 988 flags |= CLI_FULL_CONNECTION_USE_KERBEROS | 989 CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; 990 } 991 if (get_cmdline_auth_info_use_ccache(rpcclient_auth_info)) { 992 flags |= CLI_FULL_CONNECTION_USE_CCACHE; 993 } 994 995 user = talloc_strdup(frame, get_cmdline_auth_info_username(rpcclient_auth_info)); 996 SMB_ASSERT(user != NULL); 997 domain = talloc_strdup(frame, lp_workgroup()); 998 SMB_ASSERT(domain != NULL); 999 set_cmdline_auth_info_domain(rpcclient_auth_info, domain); 1000 1001 if ((q = strchr_m(user,'\\'))) { 1002 *q = 0; 1003 set_cmdline_auth_info_domain(rpcclient_auth_info, user); 1004 set_cmdline_auth_info_username(rpcclient_auth_info, q+1); 1005 } 1006 1007 1008 nt_status = cli_full_connection(&cli, global_myname(), binding->host, 1009 opt_ipaddr ? &server_ss : NULL, opt_port, 1010 "IPC$", "IPC", 1011 get_cmdline_auth_info_username(rpcclient_auth_info), 1012 get_cmdline_auth_info_domain(rpcclient_auth_info), 1013 get_cmdline_auth_info_password(rpcclient_auth_info), 1014 flags, 1015 get_cmdline_auth_info_signing_state(rpcclient_auth_info), 1016 NULL); 1017 1018 if (!NT_STATUS_IS_OK(nt_status)) { 1019 DEBUG(0,("Cannot connect to server. Error was %s\n", nt_errstr(nt_status))); 1020 result = 1; 1021 goto done; 1022 } 1023 1024 if (get_cmdline_auth_info_smb_encrypt(rpcclient_auth_info)) { 1025 nt_status = cli_cm_force_encryption(cli, 1026 get_cmdline_auth_info_username(rpcclient_auth_info), 1027 get_cmdline_auth_info_password(rpcclient_auth_info), 1028 get_cmdline_auth_info_domain(rpcclient_auth_info), 1029 "IPC$"); 1030 if (!NT_STATUS_IS_OK(nt_status)) { 1031 result = 1; 1032 goto done; 1033 } 1034 } 1035 1036#if 0 /* COMMENT OUT FOR TESTING */ 1037 memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password)); 1038#endif 1039 1040 /* Load command lists */ 1041 1042 timeout = cli_set_timeout(cli, 10000); 1043 1044 cmd_set = rpcclient_command_list; 1045 1046 while(*cmd_set) { 1047 add_command_set(*cmd_set); 1048 add_command_set(separator_command); 1049 cmd_set++; 1050 } 1051 1052 default_transport = binding->transport; 1053 1054 fetch_machine_sid(cli); 1055 1056 /* Do anything specified with -c */ 1057 if (cmdstr && cmdstr[0]) { 1058 char *cmd; 1059 char *p = cmdstr; 1060 1061 result = 0; 1062 1063 while((cmd=next_command(&p)) != NULL) { 1064 NTSTATUS cmd_result = process_cmd(rpcclient_auth_info, cli, 1065 binding, cmd); 1066 SAFE_FREE(cmd); 1067 result = NT_STATUS_IS_ERR(cmd_result); 1068 } 1069 1070 goto done; 1071 } 1072 1073 /* Loop around accepting commands */ 1074 1075 while(1) { 1076 char *line = NULL; 1077 1078 line = smb_readline("rpcclient $> ", NULL, completion_fn); 1079 1080 if (line == NULL) 1081 break; 1082 1083 if (line[0] != '\n') 1084 process_cmd(rpcclient_auth_info, cli, binding, line); 1085 SAFE_FREE(line); 1086 } 1087 1088done: 1089 if (cli != NULL) { 1090 cli_shutdown(cli); 1091 } 1092 TALLOC_FREE(frame); 1093 return result; 1094} 1095