rpcclient srvsvc commands.
[tprouty/samba.git] / source / rpcclient / rpcclient.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB client
5    Copyright (C) Andrew Tridgell 1994-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
25
26 #include "includes.h"
27
28 #ifndef REGISTER
29 #define REGISTER 0
30 #endif
31
32 extern pstring scope;
33
34 extern pstring user_socket_options;
35
36
37 extern pstring debugf;
38 extern int DEBUGLEVEL;
39
40
41 extern file_info def_finfo;
42
43 #define CNV_LANG(s) dos2unix_format(s,False)
44 #define CNV_INPUT(s) unix2dos_format(s,True)
45
46 static int process_tok(fstring tok);
47 static void cmd_help(struct client_info *info);
48 static void cmd_quit(struct client_info *info);
49
50 static struct cli_state smbcli;
51 struct cli_state *smb_cli = &smbcli;
52
53 FILE *out_hnd;
54
55 /****************************************************************************
56 initialise smb client structure
57 ****************************************************************************/
58 void rpcclient_init(void)
59 {
60         bzero(smb_cli, sizeof(smb_cli));
61         cli_initialise(smb_cli);
62 }
63
64 /****************************************************************************
65 make smb client connection
66 ****************************************************************************/
67 static BOOL rpcclient_connect(struct client_info *info)
68 {
69         struct nmb_name calling;
70         struct nmb_name called;
71
72         make_nmb_name(&called , dns_to_netbios_name(info->dest_host ), info->name_type, scope);
73         make_nmb_name(&calling, dns_to_netbios_name(info->myhostname), 0x0            , scope);
74
75         if (!cli_establish_connection(smb_cli, 
76                                   info->dest_host, &info->dest_ip, 
77                                   &calling, &called,
78                                   info->share, info->svc_type,
79                                   False, True))
80         {
81                 DEBUG(0,("rpcclient_connect: connection failed\n"));
82                 cli_shutdown(smb_cli);
83                 return False;
84         }
85
86         return True;
87 }
88
89 /****************************************************************************
90 stop the smb connection(s?)
91 ****************************************************************************/
92 static void rpcclient_stop(void)
93 {
94         cli_shutdown(smb_cli);
95 }
96 /****************************************************************************
97  This defines the commands supported by this client
98  ****************************************************************************/
99 struct
100 {
101   char *name;
102   void (*fn)(struct client_info*);
103   char *description;
104 } commands[] = 
105 {
106 #if 0
107   {"ntlogin",    cmd_netlogon_login_test, "<username> NT Domain login test"},
108 #endif
109   {"wksinfo",    cmd_wks_query_info,   "DCE/RPC - Workstation Query Info"},
110   {"srvinfo",    cmd_srv_query_info,   "DCE/RPC - Server Query Info"},
111   {"srvsessions",cmd_srv_enum_sess,    "DCE/RPC - List sessions on a server"},
112   {"srvshares",  cmd_srv_enum_shares,  "DCE/RPC - List shares on a server"},
113   {"srvconnections",cmd_srv_enum_conn, "DCE/RPC - List connections on a server"},
114   {"srvfiles",   cmd_srv_enum_files,   "DCE/RPC - List files on a server"},
115   {"lsaquery",   cmd_lsa_query_info,   "Query Info Policy (domain member or server)"},
116   {"lookupsids", cmd_lsa_lookup_sids,  "Resolve names from SIDs"},
117   {"enumusers",  cmd_sam_enum_users,   "SAM User Database Query (experimental!)"},
118   {"samuser",    cmd_sam_query_user,   "<username> SAM User Query (experimental!)"},
119   {"samtest",    cmd_sam_test      ,   "SAM User Encrypted RPC test (experimental!)"},
120   {"enumaliases",cmd_sam_enum_aliases, "SAM Aliases Database Query (experimental!)"},
121 #if 0
122   {"enumgroups", cmd_sam_enum_groups,  "SAM Group Database Query (experimental!)"},
123 #endif
124   {"samgroups",  cmd_sam_query_groups, "SAM Group Database Query (experimental!)"},
125   {"quit",       cmd_quit,        "logoff the server"},
126   {"q",          cmd_quit,        "logoff the server"},
127   {"exit",       cmd_quit,        "logoff the server"},
128   {"bye",        cmd_quit,        "logoff the server"},
129   {"help",       cmd_help,        "[command] give help on a command"},
130   {"?",          cmd_help,        "[command] give help on a command"},
131   {"!",          NULL,            "run a shell command on the local system"},
132   {"",           NULL,            NULL}
133 };
134
135
136 /****************************************************************************
137 do a (presumably graceful) quit...
138 ****************************************************************************/
139 static void cmd_quit(struct client_info *info)
140 {
141         rpcclient_stop();
142 #ifdef MEM_MAN
143         {
144                 extern FILE* dbf;
145                 smb_mem_write_status(dbf);
146                 smb_mem_write_errors(dbf);
147                 smb_mem_write_verbose(dbf);
148         }
149 #endif
150         exit(0);
151 }
152
153 /****************************************************************************
154 help
155 ****************************************************************************/
156 static void cmd_help(struct client_info *info)
157 {
158   int i=0,j;
159   fstring buf;
160
161   if (next_token(NULL,buf,NULL, sizeof(buf)))
162     {
163       if ((i = process_tok(buf)) >= 0)
164         fprintf(out_hnd, "HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);                    
165     }
166   else
167     while (commands[i].description)
168       {
169         for (j=0; commands[i].description && (j<5); j++) {
170           fprintf(out_hnd, "%-15s",commands[i].name);
171           i++;
172         }
173         fprintf(out_hnd, "\n");
174       }
175 }
176
177 /*******************************************************************
178   lookup a command string in the list of commands, including 
179   abbreviations
180   ******************************************************************/
181 static int process_tok(fstring tok)
182 {
183   int i = 0, matches = 0;
184   int cmd=0;
185   int tok_len = strlen(tok);
186   
187   while (commands[i].fn != NULL)
188     {
189       if (strequal(commands[i].name,tok))
190         {
191           matches = 1;
192           cmd = i;
193           break;
194         }
195       else if (strnequal(commands[i].name, tok, tok_len))
196         {
197           matches++;
198           cmd = i;
199         }
200       i++;
201     }
202   
203   if (matches == 0)
204     return(-1);
205   else if (matches == 1)
206     return(cmd);
207   else
208     return(-2);
209 }
210
211 /****************************************************************************
212 wait for keyboard activity, swallowing network packets
213 ****************************************************************************/
214 static void wait_keyboard(struct cli_state *cli)
215 {
216   fd_set fds;
217   struct timeval timeout;
218   
219   while (1) 
220     {
221       FD_ZERO(&fds);
222       FD_SET(cli->fd,&fds);
223       FD_SET(fileno(stdin),&fds);
224
225       timeout.tv_sec = 20;
226       timeout.tv_usec = 0;
227       sys_select(MAX(cli->fd,fileno(stdin))+1,&fds,&timeout);
228       
229       if (FD_ISSET(fileno(stdin),&fds))
230         return;
231
232       /* We deliberately use receive_smb instead of
233          client_receive_smb as we want to receive
234          session keepalives and then drop them here.
235        */
236       if (FD_ISSET(cli->fd,&fds))
237         receive_smb(cli->fd,cli->inbuf,0);
238     }  
239 }
240
241 /****************************************************************************
242   process commands from the client
243 ****************************************************************************/
244 static void do_command(struct client_info *info, char *tok, char *line)
245 {
246         int i;
247
248         if ((i = process_tok(tok)) >= 0)
249         {
250                 commands[i].fn(info);
251         }
252         else if (i == -2)
253         {
254                 fprintf(out_hnd, "%s: command abbreviation ambiguous\n", CNV_LANG(tok));
255         }
256         else
257         {
258                 fprintf(out_hnd, "%s: command not found\n", CNV_LANG(tok));
259         }
260 }
261
262 /****************************************************************************
263   process commands from the client
264 ****************************************************************************/
265 static BOOL process( struct client_info *info, char *cmd_str)
266 {
267         pstring line;
268         char *cmd = cmd_str;
269
270         if (cmd[0] != '\0') while (cmd[0] != '\0')
271         {
272                 char *p;
273                 fstring tok;
274
275                 if ((p = strchr(cmd, ';')) == 0)
276                 {
277                         strncpy(line, cmd, 999);
278                         line[1000] = '\0';
279                         cmd += strlen(cmd);
280                 }
281                 else
282                 {
283                         if (p - cmd > 999) p = cmd + 999;
284                         strncpy(line, cmd, p - cmd);
285                         line[p - cmd] = '\0';
286                         cmd = p + 1;
287                 }
288
289                 /* input language code to internal one */
290                 CNV_INPUT (line);
291
292                 /* get the first part of the command */
293                 {
294                         char *ptr = line;
295                         if (!next_token(&ptr,tok,NULL, sizeof(tok))) continue;
296                 }
297
298                 do_command(info, tok, line);
299         }
300         else while (!feof(stdin))
301         {
302                 fstring tok;
303
304                 /* display a prompt */
305                 fprintf(out_hnd, "smb: %s> ", CNV_LANG(info->cur_dir));
306                 fflush(out_hnd);
307
308 #ifdef CLIX
309                 line[0] = wait_keyboard(smb_cli);
310                 /* this might not be such a good idea... */
311                 if ( line[0] == EOF)
312                 {
313                         break;
314                 }
315 #else
316                 wait_keyboard(smb_cli);
317 #endif
318
319                 /* and get a response */
320 #ifdef CLIX
321                 fgets( &line[1],999, stdin);
322 #else
323                 if (!fgets(line,1000,stdin))
324                 {
325                         break;
326                 }
327 #endif
328
329                 /* input language code to internal one */
330                 CNV_INPUT (line);
331
332                 /* special case - first char is ! */
333                 if (*line == '!')
334                 {
335                         system(line + 1);
336                         continue;
337                 }
338
339                 fprintf(out_hnd, "%s\n", line);
340
341                 /* get the first part of the command */
342                 {
343                         char *ptr = line;
344                         if (!next_token(&ptr,tok,NULL, sizeof(tok))) continue;
345                 }
346
347                 do_command(info, tok, line);
348         }
349
350         return(True);
351 }
352
353 /****************************************************************************
354 usage on the program
355 ****************************************************************************/
356 static void usage(char *pname)
357 {
358   fprintf(out_hnd, "Usage: %s service <password> [-d debuglevel] [-l log] ",
359            pname);
360
361   fprintf(out_hnd, "\nVersion %s\n",VERSION);
362   fprintf(out_hnd, "\t-d debuglevel         set the debuglevel\n");
363   fprintf(out_hnd, "\t-l log basename.      Basename for log/debug files\n");
364   fprintf(out_hnd, "\t-n netbios name.      Use this name as my netbios name\n");
365   fprintf(out_hnd, "\t-N                    don't ask for a password\n");
366   fprintf(out_hnd, "\t-m max protocol       set the max protocol level\n");
367   fprintf(out_hnd, "\t-I dest IP            use this IP to connect to\n");
368   fprintf(out_hnd, "\t-E                    write messages to stderr instead of stdout\n");
369   fprintf(out_hnd, "\t-U username           set the network username\n");
370   fprintf(out_hnd, "\t-W workgroup          set the workgroup name\n");
371   fprintf(out_hnd, "\t-c command string     execute semicolon separated commands\n");
372   fprintf(out_hnd, "\t-t terminal code      terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n");
373   fprintf(out_hnd, "\n");
374 }
375
376 enum client_action
377 {
378         CLIENT_NONE,
379         CLIENT_IPC,
380         CLIENT_SVC
381 };
382
383 /****************************************************************************
384   main program
385 ****************************************************************************/
386  int main(int argc,char *argv[])
387 {
388         char *pname = argv[0];
389         int opt;
390         extern FILE *dbf;
391         extern char *optarg;
392         extern int optind;
393         static pstring servicesf = CONFIGFILE;
394         pstring term_code;
395         char *p;
396         BOOL got_pass = False;
397         char *cmd_str="";
398         mode_t myumask = 0755;
399         enum client_action cli_action = CLIENT_NONE;
400
401         struct client_info cli_info;
402
403         pstring password; /* local copy only, if one is entered */
404
405         out_hnd = stdout;
406
407         rpcclient_init();
408
409 #ifdef KANJI
410         pstrcpy(term_code, KANJI);
411 #else /* KANJI */
412         *term_code = 0;
413 #endif /* KANJI */
414
415         DEBUGLEVEL = 2;
416
417         cli_info.put_total_size = 0;
418         cli_info.put_total_time_ms = 0;
419         cli_info.get_total_size = 0;
420         cli_info.get_total_time_ms = 0;
421
422         cli_info.dir_total = 0;
423         cli_info.newer_than = 0;
424         cli_info.archive_level = 0;
425         cli_info.print_mode = 1;
426
427         cli_info.translation = False;
428         cli_info.recurse_dir = False;
429         cli_info.lowercase = False;
430         cli_info.prompt = True;
431         cli_info.abort_mget = True;
432
433         cli_info.dest_ip.s_addr = 0;
434         cli_info.name_type = 0x20;
435
436         pstrcpy(cli_info.cur_dir , "\\");
437         pstrcpy(cli_info.file_sel, "");
438         pstrcpy(cli_info.base_dir, "");
439         pstrcpy(smb_cli->domain, "");
440         pstrcpy(smb_cli->user_name, "");
441         pstrcpy(cli_info.myhostname, "");
442         pstrcpy(cli_info.dest_host, "");
443
444         pstrcpy(cli_info.svc_type, "A:");
445         pstrcpy(cli_info.share, "");
446         pstrcpy(cli_info.service, "");
447
448         pstrcpy(cli_info.dom.level3_sid, "");
449         pstrcpy(cli_info.dom.level3_dom, "");
450         pstrcpy(cli_info.dom.level5_sid, "");
451         pstrcpy(cli_info.dom.level5_dom, "");
452
453         smb_cli->nt_pipe_fnum   = 0xffff;
454
455         setup_logging(pname, True);
456
457         TimeInit();
458         charset_initialise();
459
460         myumask = umask(0);
461         umask(myumask);
462
463         if (getenv("USER"))
464         {
465                 pstrcpy(smb_cli->user_name,getenv("USER"));
466
467                 /* modification to support userid%passwd syntax in the USER var
468                 25.Aug.97, jdblair@uab.edu */
469
470                 if ((p=strchr(smb_cli->user_name,'%')))
471                 {
472                         *p = 0;
473                         pstrcpy(password,p+1);
474                         got_pass = True;
475                         memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
476                 }
477                 strupper(smb_cli->user_name);
478         }
479
480         password[0] = 0;
481
482         /* modification to support PASSWD environmental var
483            25.Aug.97, jdblair@uab.edu */
484         if (getenv("PASSWD"))
485         {
486                 pstrcpy(password,getenv("PASSWD"));
487         }
488
489         if (*smb_cli->user_name == 0 && getenv("LOGNAME"))
490         {
491                 pstrcpy(smb_cli->user_name,getenv("LOGNAME"));
492                 strupper(smb_cli->user_name);
493         }
494
495         if (argc < 2)
496         {
497                 usage(pname);
498                 exit(1);
499         }
500
501         if (*argv[1] != '-')
502         {
503
504                 pstrcpy(cli_info.service, argv[1]);  
505                 /* Convert any '/' characters in the service name to '\' characters */
506                 string_replace( cli_info.service, '/','\\');
507                 argc--;
508                 argv++;
509
510                 DEBUG(1,("service: %s\n", cli_info.service));
511
512                 if (count_chars(cli_info.service,'\\') < 3)
513                 {
514                         usage(pname);
515                         printf("\n%s: Not enough '\\' characters in service\n", cli_info.service);
516                         exit(1);
517                 }
518
519                 /*
520                 if (count_chars(cli_info.service,'\\') > 3)
521                 {
522                         usage(pname);
523                         printf("\n%s: Too many '\\' characters in service\n", cli_info.service);
524                         exit(1);
525                 }
526                 */
527
528                 if (argc > 1 && (*argv[1] != '-'))
529                 {
530                         got_pass = True;
531                         pstrcpy(password,argv[1]);  
532                         memset(argv[1],'X',strlen(argv[1]));
533                         argc--;
534                         argv++;
535                 }
536
537                 cli_action = CLIENT_SVC;
538         }
539
540         while ((opt = getopt(argc, argv,"s:B:O:M:S:i:N:d:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
541         {
542                 switch (opt)
543                 {
544                         case 'm':
545                         {
546                                 /* FIXME ... max_protocol seems to be funny here */
547
548                                 int max_protocol = 0;
549                                 max_protocol = interpret_protocol(optarg,max_protocol);
550                                 fprintf(stderr, "max protocol not currently supported\n");
551                                 break;
552                         }
553
554                         case 'O':
555                         {
556                                 pstrcpy(user_socket_options,optarg);
557                                 break;  
558                         }
559
560                         case 'S':
561                         {
562                                 pstrcpy(cli_info.dest_host,optarg);
563                                 strupper(cli_info.dest_host);
564                                 cli_action = CLIENT_IPC;
565                                 break;
566                         }
567
568                         case 'B':
569                         {
570                                 iface_set_default(NULL,optarg,NULL);
571                                 break;
572                         }
573
574                         case 'i':
575                         {
576                                 pstrcpy(scope, optarg);
577                                 break;
578                         }
579
580                         case 'U':
581                         {
582                                 char *lp;
583                                 pstrcpy(smb_cli->user_name,optarg);
584                                 if ((lp=strchr(smb_cli->user_name,'%')))
585                                 {
586                                         *lp = 0;
587                                         pstrcpy(password,lp+1);
588                                         got_pass = True;
589                                         memset(strchr(optarg,'%')+1,'X',strlen(password));
590                                 }
591                                 break;
592                         }
593
594                         case 'W':
595                         {
596                                 pstrcpy(smb_cli->domain,optarg);
597                                 break;
598                         }
599
600                         case 'E':
601                         {
602                                 dbf = stderr;
603                                 break;
604                         }
605
606                         case 'I':
607                         {
608                                 cli_info.dest_ip = *interpret_addr2(optarg);
609                                 if (zero_ip(cli_info.dest_ip))
610                                 {
611                                         exit(1);
612                                 }
613                                 break;
614                         }
615
616                         case 'N':
617                         {
618                                 got_pass = True;
619                                 break;
620                         }
621
622                         case 'd':
623                         {
624                                 if (*optarg == 'A')
625                                         DEBUGLEVEL = 10000;
626                                 else
627                                         DEBUGLEVEL = atoi(optarg);
628                                 break;
629                         }
630
631                         case 'l':
632                         {
633                                 slprintf(debugf, sizeof(debugf)-1,
634                                          "%s.client",optarg);
635                                 break;
636                         }
637
638                         case 'c':
639                         {
640                                 cmd_str = optarg;
641                                 got_pass = True;
642                                 break;
643                         }
644
645                         case 'h':
646                         {
647                                 usage(pname);
648                                 exit(0);
649                                 break;
650                         }
651
652                         case 's':
653                         {
654                                 pstrcpy(servicesf, optarg);
655                                 break;
656                         }
657
658                         case 't':
659                         {
660                                 pstrcpy(term_code, optarg);
661                                 break;
662                         }
663
664                         default:
665                         {
666                                 usage(pname);
667                                 exit(1);
668                                 break;
669                         }
670                 }
671         }
672
673         if (cli_action == CLIENT_NONE)
674         {
675                 usage(pname);
676                 exit(1);
677         }
678
679         DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
680
681         if (!get_myname(cli_info.myhostname, NULL))
682         {
683                 fprintf(stderr, "Failed to get my hostname.\n");
684         }
685
686         if (!lp_load(servicesf,True, False, False))
687         {
688                 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
689         }
690
691         codepage_initialise(lp_client_code_page());
692
693         if (*smb_cli->domain == 0) pstrcpy(smb_cli->domain,lp_workgroup());
694
695         load_interfaces();
696
697         if (cli_action == CLIENT_IPC)
698         {
699                 pstrcpy(cli_info.share, "IPC$");
700                 pstrcpy(cli_info.svc_type, "IPC");
701         }
702
703         fstrcpy(cli_info.mach_acct, cli_info.myhostname);
704         strupper(cli_info.mach_acct);
705         fstrcat(cli_info.mach_acct, "$");
706
707         /* set the password cache info */
708         if (got_pass)
709         {
710                 if (password[0] == 0)
711                 {
712                         pwd_set_nullpwd(&(smb_cli->pwd));
713                 }
714                 else
715                 {
716                         pwd_make_lm_nt_16(&(smb_cli->pwd), password); /* generate 16 byte hashes */
717                 }
718         }
719         else 
720         {
721                 pwd_read(&(smb_cli->pwd), "Enter Password:", True);
722         }
723
724         /* paranoia: destroy the local copy of the password */
725         bzero(password, sizeof(password)); 
726
727         /* establish connections.  nothing to stop these being re-established. */
728         rpcclient_connect(&cli_info);
729
730         DEBUG(5,("rpcclient_connect: smb_cli->fd:%d\n", smb_cli->fd));
731         if (smb_cli->fd <= 0)
732         {
733                 fprintf(stderr, "warning: connection could not be established to %s<%02x>\n",
734                                  cli_info.dest_host, cli_info.name_type);
735                 fprintf(stderr, "this version of smbclient may crash if you proceed\n");
736                 exit(-1);
737         }
738
739         switch (cli_action)
740         {
741                 case CLIENT_IPC:
742                 {
743                         process(&cli_info, cmd_str);
744                         break;
745                 }
746
747                 default:
748                 {
749                         fprintf(stderr, "unknown client action requested\n");
750                         break;
751                 }
752         }
753
754         rpcclient_stop();
755
756         return(0);
757 }