2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
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.
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.
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.
32 extern pstring debugf
;
34 extern pstring global_myname
;
36 extern pstring user_socket_options
;
39 extern int DEBUGLEVEL
;
42 extern file_info def_finfo
;
44 #define CNV_LANG(s) dos2unix_format(s,False)
45 #define CNV_INPUT(s) unix2dos_format(s,True)
47 static int process_tok(fstring tok
);
48 static void cmd_help(struct client_info
*info
);
49 static void cmd_quit(struct client_info
*info
);
51 static struct cli_state smbcli
;
52 struct cli_state
*smb_cli
= &smbcli
;
56 /****************************************************************************
57 initialise smb client structure
58 ****************************************************************************/
59 void rpcclient_init(void)
61 bzero(smb_cli
, sizeof(smb_cli
));
62 cli_initialise(smb_cli
);
63 smb_cli
->capabilities
|= CAP_NT_SMBS
| CAP_STATUS32
;
66 /****************************************************************************
67 make smb client connection
68 ****************************************************************************/
69 static BOOL
rpcclient_connect(struct client_info
*info
)
71 struct nmb_name calling
;
72 struct nmb_name called
;
74 make_nmb_name(&called
, dns_to_netbios_name(info
->dest_host
), info
->name_type
, scope
);
75 make_nmb_name(&calling
, dns_to_netbios_name(info
->myhostname
), 0x0 , scope
);
77 if (!cli_establish_connection(smb_cli
,
78 info
->dest_host
, &info
->dest_ip
,
80 info
->share
, info
->svc_type
,
83 DEBUG(0,("rpcclient_connect: connection failed\n"));
84 cli_shutdown(smb_cli
);
91 /****************************************************************************
92 stop the smb connection(s?)
93 ****************************************************************************/
94 static void rpcclient_stop(void)
96 cli_shutdown(smb_cli
);
98 /****************************************************************************
99 This defines the commands supported by this client
100 ****************************************************************************/
104 void (*fn
)(struct client_info
*);
108 {"regenum", cmd_reg_enum
, "<keyname> Registry Enumeration (keys, values)"},
109 {"regdeletekey",cmd_reg_delete_key
, "<keyname> Registry Key Delete"},
110 {"regcreatekey",cmd_reg_create_key
, "<keyname> [keyclass] Registry Key Create"},
111 {"regquerykey",cmd_reg_query_key
, "<keyname> Registry Key Query"},
112 {"regdeleteval",cmd_reg_delete_val
, "<valname> Registry Value Delete"},
113 {"regcreateval",cmd_reg_create_val
, "<valname> <valtype> <value> Registry Key Create"},
114 {"reggetsec", cmd_reg_get_key_sec
, "<keyname> Registry Key Security"},
115 {"regtestsec", cmd_reg_test_key_sec
, "<keyname> Test Registry Key Security"},
116 {"ntlogin", cmd_netlogon_login_test
, "[username] [password] NT Domain login test"},
117 {"wksinfo", cmd_wks_query_info
, "Workstation Query Info"},
118 {"srvinfo", cmd_srv_query_info
, "Server Query Info"},
119 {"srvsessions",cmd_srv_enum_sess
, "List sessions on a server"},
120 {"srvshares", cmd_srv_enum_shares
, "List shares on a server"},
121 {"srvconnections",cmd_srv_enum_conn
, "List connections on a server"},
122 {"srvfiles", cmd_srv_enum_files
, "List files on a server"},
123 {"lsaquery", cmd_lsa_query_info
, "Query Info Policy (domain member or server)"},
124 {"lookupsids", cmd_lsa_lookup_sids
, "Resolve names from SIDs"},
125 {"enumusers", cmd_sam_enum_users
, "SAM User Database Query (experimental!)"},
126 {"ntpass", cmd_sam_ntchange_pwd
, "NT SAM Password Change"},
127 {"samuser", cmd_sam_query_user
, "<username> SAM User Query (experimental!)"},
128 {"samtest", cmd_sam_test
, "SAM User Encrypted RPC test (experimental!)"},
129 {"enumaliases",cmd_sam_enum_aliases
, "SAM Aliases Database Query (experimental!)"},
131 {"enumgroups", cmd_sam_enum_groups
, "SAM Group Database Query (experimental!)"},
133 {"samgroups", cmd_sam_query_groups
, "SAM Group Database Query (experimental!)"},
134 {"quit", cmd_quit
, "logoff the server"},
135 {"q", cmd_quit
, "logoff the server"},
136 {"exit", cmd_quit
, "logoff the server"},
137 {"bye", cmd_quit
, "logoff the server"},
138 {"help", cmd_help
, "[command] give help on a command"},
139 {"?", cmd_help
, "[command] give help on a command"},
140 {"!", NULL
, "run a shell command on the local system"},
145 /****************************************************************************
146 do a (presumably graceful) quit...
147 ****************************************************************************/
148 static void cmd_quit(struct client_info
*info
)
154 smb_mem_write_status(dbf
);
155 smb_mem_write_errors(dbf
);
156 smb_mem_write_verbose(dbf
);
162 /****************************************************************************
164 ****************************************************************************/
165 static void cmd_help(struct client_info
*info
)
170 if (next_token(NULL
,buf
,NULL
, sizeof(buf
)))
172 if ((i
= process_tok(buf
)) >= 0)
173 fprintf(out_hnd
, "HELP %s:\n\t%s\n\n",commands
[i
].name
,commands
[i
].description
);
176 while (commands
[i
].description
)
178 for (j
=0; commands
[i
].description
&& (j
<5); j
++) {
179 fprintf(out_hnd
, "%-15s",commands
[i
].name
);
182 fprintf(out_hnd
, "\n");
186 /*******************************************************************
187 lookup a command string in the list of commands, including
189 ******************************************************************/
190 static int process_tok(fstring tok
)
192 int i
= 0, matches
= 0;
194 int tok_len
= strlen(tok
);
196 while (commands
[i
].fn
!= NULL
)
198 if (strequal(commands
[i
].name
,tok
))
204 else if (strnequal(commands
[i
].name
, tok
, tok_len
))
214 else if (matches
== 1)
220 /****************************************************************************
221 wait for keyboard activity, swallowing network packets
222 ****************************************************************************/
223 static void wait_keyboard(struct cli_state
*cli
)
226 struct timeval timeout
;
231 FD_SET(cli
->fd
,&fds
);
232 FD_SET(fileno(stdin
),&fds
);
236 sys_select(MAX(cli
->fd
,fileno(stdin
))+1,&fds
,&timeout
);
238 if (FD_ISSET(fileno(stdin
),&fds
))
241 /* We deliberately use receive_smb instead of
242 client_receive_smb as we want to receive
243 session keepalives and then drop them here.
245 if (FD_ISSET(cli
->fd
,&fds
))
246 receive_smb(cli
->fd
,cli
->inbuf
,0);
250 /****************************************************************************
251 process commands from the client
252 ****************************************************************************/
253 static void do_command(struct client_info
*info
, char *tok
, char *line
)
257 if ((i
= process_tok(tok
)) >= 0)
259 commands
[i
].fn(info
);
263 fprintf(out_hnd
, "%s: command abbreviation ambiguous\n", CNV_LANG(tok
));
267 fprintf(out_hnd
, "%s: command not found\n", CNV_LANG(tok
));
271 /****************************************************************************
272 process commands from the client
273 ****************************************************************************/
274 static BOOL
process( struct client_info
*info
, char *cmd_str
)
279 if (cmd
[0] != '\0') while (cmd
[0] != '\0')
284 if ((p
= strchr(cmd
, ';')) == 0)
286 strncpy(line
, cmd
, 999);
292 if (p
- cmd
> 999) p
= cmd
+ 999;
293 strncpy(line
, cmd
, p
- cmd
);
294 line
[p
- cmd
] = '\0';
298 /* input language code to internal one */
301 /* get the first part of the command */
304 if (!next_token(&ptr
,tok
,NULL
, sizeof(tok
))) continue;
307 do_command(info
, tok
, line
);
309 else while (!feof(stdin
))
313 /* display a prompt */
314 fprintf(out_hnd
, "smb: %s> ", CNV_LANG(info
->cur_dir
));
318 line
[0] = wait_keyboard(smb_cli
);
319 /* this might not be such a good idea... */
325 wait_keyboard(smb_cli
);
328 /* and get a response */
330 fgets( &line
[1],999, stdin
);
332 if (!fgets(line
,1000,stdin
))
338 /* input language code to internal one */
341 /* special case - first char is ! */
348 fprintf(out_hnd
, "%s\n", line
);
350 /* get the first part of the command */
353 if (!next_token(&ptr
,tok
,NULL
, sizeof(tok
))) continue;
356 do_command(info
, tok
, line
);
362 /****************************************************************************
364 ****************************************************************************/
365 static void usage(char *pname
)
367 fprintf(out_hnd
, "Usage: %s service <password> [-d debuglevel] [-l log] ",
370 fprintf(out_hnd
, "\nVersion %s\n",VERSION
);
371 fprintf(out_hnd
, "\t-d debuglevel set the debuglevel\n");
372 fprintf(out_hnd
, "\t-l log basename. Basename for log/debug files\n");
373 fprintf(out_hnd
, "\t-n netbios name. Use this name as my netbios name\n");
374 fprintf(out_hnd
, "\t-N don't ask for a password\n");
375 fprintf(out_hnd
, "\t-m max protocol set the max protocol level\n");
376 fprintf(out_hnd
, "\t-I dest IP use this IP to connect to\n");
377 fprintf(out_hnd
, "\t-E write messages to stderr instead of stdout\n");
378 fprintf(out_hnd
, "\t-U username set the network username\n");
379 fprintf(out_hnd
, "\t-W workgroup set the workgroup name\n");
380 fprintf(out_hnd
, "\t-c command string execute semicolon separated commands\n");
381 fprintf(out_hnd
, "\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n");
382 fprintf(out_hnd
, "\n");
392 /****************************************************************************
394 ****************************************************************************/
395 int main(int argc
,char *argv
[])
397 BOOL interactive
= True
;
403 static pstring servicesf
= CONFIGFILE
;
406 BOOL got_pass
= False
;
408 mode_t myumask
= 0755;
409 enum client_action cli_action
= CLIENT_NONE
;
411 struct client_info cli_info
;
413 pstring password
; /* local copy only, if one is entered */
416 fstrcpy(debugf
, argv
[0]);
421 pstrcpy(term_code
, KANJI
);
428 cli_info
.put_total_size
= 0;
429 cli_info
.put_total_time_ms
= 0;
430 cli_info
.get_total_size
= 0;
431 cli_info
.get_total_time_ms
= 0;
433 cli_info
.dir_total
= 0;
434 cli_info
.newer_than
= 0;
435 cli_info
.archive_level
= 0;
436 cli_info
.print_mode
= 1;
438 cli_info
.translation
= False
;
439 cli_info
.recurse_dir
= False
;
440 cli_info
.lowercase
= False
;
441 cli_info
.prompt
= True
;
442 cli_info
.abort_mget
= True
;
444 cli_info
.dest_ip
.s_addr
= 0;
445 cli_info
.name_type
= 0x20;
447 pstrcpy(cli_info
.cur_dir
, "\\");
448 pstrcpy(cli_info
.file_sel
, "");
449 pstrcpy(cli_info
.base_dir
, "");
450 pstrcpy(smb_cli
->domain
, "");
451 pstrcpy(smb_cli
->user_name
, "");
452 pstrcpy(cli_info
.myhostname
, "");
453 pstrcpy(cli_info
.dest_host
, "");
455 pstrcpy(cli_info
.svc_type
, "A:");
456 pstrcpy(cli_info
.share
, "");
457 pstrcpy(cli_info
.service
, "");
459 ZERO_STRUCT(cli_info
.dom
.level3_sid
);
460 ZERO_STRUCT(cli_info
.dom
.level5_sid
);
461 fstrcpy(cli_info
.dom
.level3_dom
, "");
462 fstrcpy(cli_info
.dom
.level5_dom
, "");
464 smb_cli
->nt_pipe_fnum
= 0xffff;
467 charset_initialise();
472 if (!get_myname(global_myname
, NULL
))
474 fprintf(stderr
, "Failed to get my hostname.\n");
479 pstrcpy(smb_cli
->user_name
,getenv("USER"));
481 /* modification to support userid%passwd syntax in the USER var
482 25.Aug.97, jdblair@uab.edu */
484 if ((p
=strchr(smb_cli
->user_name
,'%')))
487 pstrcpy(password
,p
+1);
489 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password
));
491 strupper(smb_cli
->user_name
);
496 /* modification to support PASSWD environmental var
497 25.Aug.97, jdblair@uab.edu */
498 if (getenv("PASSWD"))
500 pstrcpy(password
,getenv("PASSWD"));
503 if (*smb_cli
->user_name
== 0 && getenv("LOGNAME"))
505 pstrcpy(smb_cli
->user_name
,getenv("LOGNAME"));
506 strupper(smb_cli
->user_name
);
518 pstrcpy(cli_info
.service
, argv
[1]);
519 /* Convert any '/' characters in the service name to '\' characters */
520 string_replace( cli_info
.service
, '/','\\');
524 fprintf(out_hnd
, "service: %s\n", cli_info
.service
);
526 if (count_chars(cli_info
.service
,'\\') < 3)
529 printf("\n%s: Not enough '\\' characters in service\n", cli_info
.service
);
534 if (count_chars(cli_info.service,'\\') > 3)
537 printf("\n%s: Too many '\\' characters in service\n", cli_info.service);
542 if (argc
> 1 && (*argv
[1] != '-'))
545 pstrcpy(password
,argv
[1]);
546 memset(argv
[1],'X',strlen(argv
[1]));
551 cli_action
= CLIENT_SVC
;
554 while ((opt
= getopt(argc
, argv
,"s:B:O:M:S:i:N:n:d:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF
)
560 /* FIXME ... max_protocol seems to be funny here */
562 int max_protocol
= 0;
563 max_protocol
= interpret_protocol(optarg
,max_protocol
);
564 fprintf(stderr
, "max protocol not currently supported\n");
570 pstrcpy(user_socket_options
,optarg
);
576 pstrcpy(cli_info
.dest_host
,optarg
);
577 strupper(cli_info
.dest_host
);
578 cli_action
= CLIENT_IPC
;
584 iface_set_default(NULL
,optarg
,NULL
);
590 pstrcpy(scope
, optarg
);
597 pstrcpy(smb_cli
->user_name
,optarg
);
598 if ((lp
=strchr(smb_cli
->user_name
,'%')))
601 pstrcpy(password
,lp
+1);
603 memset(strchr(optarg
,'%')+1,'X',strlen(password
));
610 pstrcpy(smb_cli
->domain
,optarg
);
622 cli_info
.dest_ip
= *interpret_addr2(optarg
);
623 if (zero_ip(cli_info
.dest_ip
))
632 fstrcpy(global_myname
, optarg
);
647 DEBUGLEVEL
= atoi(optarg
);
653 slprintf(debugf
, sizeof(debugf
)-1,
654 "%s.client", optarg
);
675 pstrcpy(servicesf
, optarg
);
681 pstrcpy(term_code
, optarg
);
694 setup_logging(debugf
, interactive
);
696 if (cli_action
== CLIENT_NONE
)
702 strupper(global_myname
);
703 fstrcpy(cli_info
.myhostname
, global_myname
);
705 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION
));
707 if (!lp_load(servicesf
,True
, False
, False
))
709 fprintf(stderr
, "Can't load %s - run testparm to debug it\n", servicesf
);
712 codepage_initialise(lp_client_code_page());
714 if (*smb_cli
->domain
== 0) pstrcpy(smb_cli
->domain
,lp_workgroup());
718 if (cli_action
== CLIENT_IPC
)
720 pstrcpy(cli_info
.share
, "IPC$");
721 pstrcpy(cli_info
.svc_type
, "IPC");
724 fstrcpy(cli_info
.mach_acct
, cli_info
.myhostname
);
725 strupper(cli_info
.mach_acct
);
726 fstrcat(cli_info
.mach_acct
, "$");
728 /* set the password cache info */
731 if (password
[0] == 0)
733 pwd_set_nullpwd(&(smb_cli
->pwd
));
737 pwd_make_lm_nt_16(&(smb_cli
->pwd
), password
); /* generate 16 byte hashes */
742 pwd_read(&(smb_cli
->pwd
), "Enter Password:", True
);
745 /* paranoia: destroy the local copy of the password */
746 bzero(password
, sizeof(password
));
748 /* establish connections. nothing to stop these being re-established. */
749 rpcclient_connect(&cli_info
);
751 DEBUG(5,("rpcclient_connect: smb_cli->fd:%d\n", smb_cli
->fd
));
752 if (smb_cli
->fd
<= 0)
754 fprintf(stderr
, "warning: connection could not be established to %s<%02x>\n",
755 cli_info
.dest_host
, cli_info
.name_type
);
756 fprintf(stderr
, "this version of smbclient may crash if you proceed\n");
764 process(&cli_info
, cmd_str
);
770 fprintf(stderr
, "unknown client action requested\n");