1 | /******************************************************************************
|
---|
2 | *
|
---|
3 | * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
|
---|
4 | * www.mindbright.se, [email protected]
|
---|
5 | *
|
---|
6 | * This program is free software; you can redistribute it and/or modify
|
---|
7 | * it under the terms of the GNU General Public License as published by
|
---|
8 | * the Free Software Foundation; either version 2 of the License, or
|
---|
9 | * (at your option) any later version.
|
---|
10 | *
|
---|
11 | * This program is distributed in the hope that it will be useful,
|
---|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | * GNU General Public License for more details.
|
---|
15 | *
|
---|
16 | *****************************************************************************
|
---|
17 | * $Author: mats $
|
---|
18 | * $Date: 2000/03/07 16:44:34 $
|
---|
19 | * $Name: rel1-2-1 $
|
---|
20 | *****************************************************************************/
|
---|
21 | package mindbright.ssh;
|
---|
22 |
|
---|
23 | import java.io.*;
|
---|
24 | import java.awt.*;
|
---|
25 |
|
---|
26 | import mindbright.terminal.*;
|
---|
27 | import mindbright.security.*;
|
---|
28 |
|
---|
29 | public final class SSHCommandShellImpl implements SSHCommandShell {
|
---|
30 |
|
---|
31 | static Toolkit toolkit = Toolkit.getDefaultToolkit();
|
---|
32 |
|
---|
33 | SSHStdIO stdio;
|
---|
34 |
|
---|
35 | int escapeIdx;
|
---|
36 | String escapeString = "~$";
|
---|
37 |
|
---|
38 | public void setStdIO(SSHStdIO stdio) {
|
---|
39 | this.stdio = stdio;
|
---|
40 | }
|
---|
41 |
|
---|
42 | // One hell of a kludge all this... (a bit better now at least...)
|
---|
43 | //
|
---|
44 | public String getNextArg(String args) {
|
---|
45 | int i = args.indexOf(' ');
|
---|
46 | if(i > -1)
|
---|
47 | args = args.substring(0, i);
|
---|
48 | return args;
|
---|
49 | }
|
---|
50 | public String[] makeArgv(String cmdLine) {
|
---|
51 | String[] argv = new String[32];
|
---|
52 | String[] argvRet;
|
---|
53 | int n = 0, i;
|
---|
54 | while(cmdLine != null) {
|
---|
55 | argv[n++] = getNextArg(cmdLine);
|
---|
56 | i = cmdLine.indexOf(' ');
|
---|
57 | if(i > -1) {
|
---|
58 | cmdLine = cmdLine.substring(i);
|
---|
59 | cmdLine = cmdLine.trim();
|
---|
60 | } else
|
---|
61 | cmdLine = null;
|
---|
62 | }
|
---|
63 | argvRet = new String[n];
|
---|
64 | System.arraycopy(argv, 0, argvRet, 0, n);
|
---|
65 | return argvRet;
|
---|
66 | }
|
---|
67 | public void doHelp() {
|
---|
68 | stdio.println("The following commands are available:");
|
---|
69 | stdio.println("");
|
---|
70 | stdio.println("go Start SSH-session with current settings.");
|
---|
71 | stdio.println("quit Quit program (or disconnect if connected).");
|
---|
72 | stdio.println("add <l|r> [/<plug>/]<port>:<host>:<port> (see below).");
|
---|
73 | stdio.println("del l <local-host>:<listen-port>|* Delete local forward (* = all).");
|
---|
74 | stdio.println("del r <listen-port>|* Delete remote forward (* = all).");
|
---|
75 | stdio.println("list [ssh | term] Lists ssh- and/or terminal-settings.");
|
---|
76 | stdio.println("set [<parameter> <value>] Set value of a ssh-parameter.");
|
---|
77 | stdio.println("tset [<parameter> <value>] Set value of a terminal-parameter.");
|
---|
78 | stdio.println("key [<bits>] Generate RSA key-pair (of length <bits>).");
|
---|
79 | stdio.println("help Display this list, but you knew that :-).");
|
---|
80 | stdio.println("");
|
---|
81 | stdio.println("(do 'set' without arguments to list parameter-usage)");
|
---|
82 | stdio.println("");
|
---|
83 | stdio.println("Examples of adding a remote/local tunnel:");
|
---|
84 | stdio.println("> add r 4711:www.foo.com:80 Adds a remote tunnel at port 4711 back to");
|
---|
85 | stdio.println(" www.foo.com port 80 without a plugin,");
|
---|
86 | stdio.println(" i.e. default tunneling behaviour.");
|
---|
87 | stdio.println("> add l /ftp/4711:ftp.bar.com:21 Adds a local tunnel going to ftp.bar.com");
|
---|
88 | stdio.println(" port 21 using the ftp protocol-plugin to");
|
---|
89 | stdio.println(" handle protocol specific needs.");
|
---|
90 | stdio.println("");
|
---|
91 | stdio.println("NOTE: The first character of the command can be used instead of the full word.");
|
---|
92 | stdio.println("");
|
---|
93 | }
|
---|
94 | public void doHelpSet() {
|
---|
95 | int i;
|
---|
96 | stdio.println("SSH-parameters:");
|
---|
97 | stdio.println("");
|
---|
98 | for(i = 0; i < stdio.client.propsHandler.defaultPropDesc.length; i++) {
|
---|
99 | stdio.println(stdio.client.propsHandler.defaultPropDesc[i][stdio.client.propsHandler.PROP_NAME] + "\t: " +
|
---|
100 | stdio.client.propsHandler.defaultPropDesc[i][stdio.client.propsHandler.PROP_DESC]);
|
---|
101 | }
|
---|
102 | stdio.println("(to see possible parameter-values use 'list')");
|
---|
103 | }
|
---|
104 | public void doHelpTSet() {
|
---|
105 | int i;
|
---|
106 | stdio.println("Terminal-parameters:");
|
---|
107 | stdio.println("");
|
---|
108 | for(i = 0; i < TerminalDefProps.defaultPropDesc.length; i++) {
|
---|
109 | stdio.println(TerminalDefProps.defaultPropDesc[i][TerminalDefProps.PROP_NAME] + "\t: " +
|
---|
110 | TerminalDefProps.defaultPropDesc[i][TerminalDefProps.PROP_DESC]);
|
---|
111 | }
|
---|
112 | stdio.println("(to see possible parameter-values use 'list')");
|
---|
113 | }
|
---|
114 | public void doAdd(String[] argv) {
|
---|
115 | if(argv.length < 3 || (!argv[1].equals("l") && !argv[1].equals("r")))
|
---|
116 | doHelp();
|
---|
117 | else {
|
---|
118 | try {
|
---|
119 | if(argv[1].equals("l"))
|
---|
120 | stdio.client.propsHandler.setProperty("local" + stdio.client.localForwards.size(), argv[2]);
|
---|
121 | else
|
---|
122 | stdio.client.propsHandler.setProperty("remote" + stdio.client.remoteForwards.size(), argv[2]);
|
---|
123 | } catch (Exception e) {
|
---|
124 | doHelp();
|
---|
125 | }
|
---|
126 | }
|
---|
127 | }
|
---|
128 | public void doDel(String[] argv) {
|
---|
129 | if(argv.length < 3 || (!argv[1].equals("l") && !argv[1].equals("r")))
|
---|
130 | doHelp();
|
---|
131 | else {
|
---|
132 | try {
|
---|
133 | int port;
|
---|
134 | if(argv[2].equals("*"))
|
---|
135 | port = -1;
|
---|
136 | if(argv[1].equals("l")) {
|
---|
137 | int d = argv[2].indexOf(':');
|
---|
138 | String host;
|
---|
139 | host = argv[2].substring(0, d);
|
---|
140 | port = Integer.parseInt(argv[2].substring(d + 1));
|
---|
141 | stdio.client.delLocalPortForward(host, port);
|
---|
142 | } else {
|
---|
143 | port = Integer.parseInt(argv[2]);
|
---|
144 | stdio.client.delRemotePortForward(port);
|
---|
145 | }
|
---|
146 | } catch (Exception e) {
|
---|
147 | doHelp();
|
---|
148 | }
|
---|
149 | }
|
---|
150 | }
|
---|
151 | public void doListSSH() {
|
---|
152 | int i;
|
---|
153 | stdio.println("");
|
---|
154 | if(stdio.term != null)
|
---|
155 | stdio.term.setAttribute(Terminal.ATTR_BOLD, true);
|
---|
156 | stdio.println("SSH settings:");
|
---|
157 | if(stdio.term != null)
|
---|
158 | stdio.term.setAttribute(Terminal.ATTR_BOLD, false);
|
---|
159 |
|
---|
160 | for(i = 0; i < stdio.client.propsHandler.defaultPropDesc.length; i++) {
|
---|
161 | String propName = stdio.client.propsHandler.defaultPropDesc[i][stdio.client.propsHandler.PROP_NAME];
|
---|
162 | String propVal = stdio.client.propsHandler.getProperty(propName);
|
---|
163 | stdio.println(propName + "\t: " + (propVal.equals("") ? "<not set>" : propVal) + " " +
|
---|
164 | stdio.client.propsHandler.defaultPropDesc[i][stdio.client.propsHandler.PROP_ALLOWED]);
|
---|
165 | }
|
---|
166 |
|
---|
167 | stdio.println("");
|
---|
168 | stdio.println("local tunnels:");
|
---|
169 | for(i = 0; i < stdio.client.localForwards.size(); i++) {
|
---|
170 | SSHClient.LocalForward fwd = (SSHClient.LocalForward) stdio.client.localForwards.elementAt(i);
|
---|
171 | stdio.println("\tlocal: " + fwd.localPort + "\tremote: " + fwd.remoteHost + "/" +
|
---|
172 | fwd.remotePort + " (plugin: " + fwd.plugin + ")");
|
---|
173 | }
|
---|
174 | if(i == 0)
|
---|
175 | stdio.println("\t<none>");
|
---|
176 | stdio.println("remote tunnels:");
|
---|
177 | for(i = 0; i < stdio.client.remoteForwards.size(); i++) {
|
---|
178 | SSHClient.RemoteForward fwd = (SSHClient.RemoteForward) stdio.client.remoteForwards.elementAt(i);
|
---|
179 | stdio.println("\tremote: " + fwd.remotePort + "\tlocal: " + fwd.localHost + "/" +
|
---|
180 | fwd.localPort + " (plugin: " + fwd.plugin + ")");
|
---|
181 | }
|
---|
182 | if(i == 0)
|
---|
183 | stdio.println("\t<none>");
|
---|
184 | stdio.println("");
|
---|
185 |
|
---|
186 | if(stdio.client.isOpened()) {
|
---|
187 | if(stdio.term != null)
|
---|
188 | stdio.term.setAttribute(Terminal.ATTR_BOLD, true);
|
---|
189 | stdio.println("Currently active tunnels:");
|
---|
190 | if(stdio.term != null)
|
---|
191 | stdio.term.setAttribute(Terminal.ATTR_BOLD, false);
|
---|
192 | String[] list = stdio.controller.listTunnels();
|
---|
193 | if(list.length == 0)
|
---|
194 | stdio.print("\t<none>");
|
---|
195 | else {
|
---|
196 | for(i = 0; i < list.length; i++)
|
---|
197 | stdio.println("\t" + list[i]);
|
---|
198 | }
|
---|
199 | stdio.println("");
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 | public void doListTerm() {
|
---|
204 | int i;
|
---|
205 | stdio.println("");
|
---|
206 |
|
---|
207 | if(stdio.term != null) {
|
---|
208 | TerminalWin termwin = (TerminalWin)stdio.term;
|
---|
209 | stdio.term.setAttribute(Terminal.ATTR_BOLD, true);
|
---|
210 | stdio.println("Terminal settings:");
|
---|
211 | stdio.term.setAttribute(Terminal.ATTR_BOLD, false);
|
---|
212 |
|
---|
213 | for(i = 0; i < TerminalDefProps.defaultPropDesc.length; i++) {
|
---|
214 | String propName = TerminalDefProps.defaultPropDesc[i][TerminalDefProps.PROP_NAME];
|
---|
215 | stdio.println(propName + "\t: " + termwin.getProperty(propName) + " " +
|
---|
216 | TerminalDefProps.defaultPropDesc[i][TerminalDefProps.PROP_ALLOWED]);
|
---|
217 | }
|
---|
218 |
|
---|
219 | stdio.println("");
|
---|
220 | }
|
---|
221 | }
|
---|
222 |
|
---|
223 | public void doSet(String[] argv) {
|
---|
224 | if(argv.length < 3) {
|
---|
225 | doHelpSet();
|
---|
226 | } else {
|
---|
227 | try {
|
---|
228 | String prm = argv[1];
|
---|
229 | String arg = argv[2];
|
---|
230 | stdio.client.propsHandler.setProperty(prm, arg);
|
---|
231 | } catch (Exception e) {
|
---|
232 | stdio.println(e.getMessage());
|
---|
233 | stdio.println("(use 'set' without parameters to get help on available parameters)");
|
---|
234 | }
|
---|
235 | }
|
---|
236 | }
|
---|
237 | public void doTSet(String[] argv) {
|
---|
238 | if(argv.length < 3) {
|
---|
239 | doHelpTSet();
|
---|
240 | } else {
|
---|
241 | String prm = argv[1];
|
---|
242 | String arg = argv[2];
|
---|
243 | TerminalWin termwin = null;
|
---|
244 | if(stdio.term instanceof TerminalWin)
|
---|
245 | termwin = (TerminalWin)stdio.term;
|
---|
246 | if(termwin != null) {
|
---|
247 | try {
|
---|
248 | termwin.setProperty(prm, arg);
|
---|
249 | } catch (Exception e) {
|
---|
250 | stdio.println(e.getMessage());
|
---|
251 | stdio.println("(use 'tset' without parameters to get help on available parameters)");
|
---|
252 | }
|
---|
253 | } else {
|
---|
254 | stdio.println("Can't set terminal-parameters in dumb-console mode.");
|
---|
255 | }
|
---|
256 | }
|
---|
257 | }
|
---|
258 | public void doGenKey(String[] argv) {
|
---|
259 | String fileName, passwd, comment;
|
---|
260 | KeyPair kp;
|
---|
261 | int bits = 1024;
|
---|
262 |
|
---|
263 | stdio.println("");
|
---|
264 |
|
---|
265 | if(argv.length > 1) {
|
---|
266 | try {
|
---|
267 | bits = Integer.parseInt(argv[1]);
|
---|
268 | } catch(Exception e) {
|
---|
269 | stdio.println("(invalid <bits>, using default 1024)");
|
---|
270 | }
|
---|
271 | }
|
---|
272 |
|
---|
273 | try {
|
---|
274 | stdio.println("The key-pair will be stored in a file with the name you enter.");
|
---|
275 | stdio.println("Files are stored in '" + stdio.client.propsHandler.getSSHHomeDir() + "' if no path is given.");
|
---|
276 | stdio.println("(note: the public key will also be stored in a file with ext. '.pub')");
|
---|
277 | fileName = stdio.promptLine("Filename to save identity in: " , "", false);
|
---|
278 | if(!fileName.startsWith(File.separator))
|
---|
279 | fileName = stdio.client.propsHandler.getSSHHomeDir() + fileName;
|
---|
280 | do {
|
---|
281 | passwd = stdio.promptLine("Password to protect private key: " , "", true);
|
---|
282 | } while(!passwd.equals(stdio.promptLine("Password again: " , "", true)));
|
---|
283 | comment = stdio.promptLine("Comment to store in key-files: " , "", false);
|
---|
284 | stdio.print("Generating identity of length " + bits + "...");
|
---|
285 | try {
|
---|
286 | Thread.sleep(100); // !!! let the text show... (?)
|
---|
287 | } catch (InterruptedException e) {
|
---|
288 | // !!!
|
---|
289 | }
|
---|
290 | kp = SSH.generateRSAKeyPair(bits, SSH.secureRandom());
|
---|
291 | stdio.println("done");
|
---|
292 | String pks = SSH.generateKeyFiles(kp, fileName, passwd, comment);
|
---|
293 | stdio.setSelection(pks);
|
---|
294 | stdio.selectionAvailable(true);
|
---|
295 | } catch (Exception ee) {
|
---|
296 | stdio.println("An error occured while generating key...");
|
---|
297 | }
|
---|
298 | stdio.println("");
|
---|
299 | }
|
---|
300 |
|
---|
301 | public boolean doCommandShell() {
|
---|
302 | boolean retVal = true;
|
---|
303 | stdio.println("");
|
---|
304 | stdio.println("...entering local command-shell (type 'h' for help).");
|
---|
305 | stdio.println("");
|
---|
306 | try {
|
---|
307 | boolean keepRunning = true;
|
---|
308 | String[] argv;
|
---|
309 | while(keepRunning) {
|
---|
310 | String cmdLine = stdio.promptLine("mindterm> ", null, false);
|
---|
311 | String cmd;
|
---|
312 | cmdLine = cmdLine.toLowerCase();
|
---|
313 | cmdLine = cmdLine.trim();
|
---|
314 | if(cmdLine.equals(""))
|
---|
315 | continue;
|
---|
316 | argv = makeArgv(cmdLine);
|
---|
317 | cmd = argv[0];
|
---|
318 | if(cmd.equals("l") || cmd.equals("list")) {
|
---|
319 | if(argv.length > 1) {
|
---|
320 | if(argv[1].equals("ssh") || argv[1].equals("term")) {
|
---|
321 | if(argv[1].equals("ssh"))
|
---|
322 | doListSSH();
|
---|
323 | else
|
---|
324 | doListTerm();
|
---|
325 | stdio.println("(permitted values are in parentheses on the right)");
|
---|
326 | stdio.println("");
|
---|
327 | } else
|
---|
328 | stdio.println("usage: 'list [ssh | term]'");
|
---|
329 | } else {
|
---|
330 | doListSSH();
|
---|
331 | doListTerm();
|
---|
332 | stdio.println("(permitted values are in parentheses on the right)");
|
---|
333 | stdio.println("");
|
---|
334 | }
|
---|
335 | } else if(cmd.equals("a") || cmd.equals("add")) {
|
---|
336 | doAdd(argv);
|
---|
337 | } else if(cmd.equals("d") || cmd.equals("del")) {
|
---|
338 | doDel(argv);
|
---|
339 | } else if(cmd.equals("s") || cmd.equals("set")) {
|
---|
340 | doSet(argv);
|
---|
341 | } else if(cmd.equals("t") || cmd.equals("ts") || cmd.equals("tset")) {
|
---|
342 | doTSet(argv);
|
---|
343 | } else if(cmd.equals("help") || cmd.equals("?") || cmd.equals("h")) {
|
---|
344 | doHelp();
|
---|
345 | } else if(cmd.equals("go") || cmd.equals("g")) {
|
---|
346 | retVal = true;
|
---|
347 | keepRunning = false;
|
---|
348 | } else if(cmd.equals("key")) {
|
---|
349 | doGenKey(argv);
|
---|
350 | } else if(cmd.equals("q") || cmd.equals("quit")) {
|
---|
351 | retVal = false;
|
---|
352 | keepRunning = false;
|
---|
353 | } else {
|
---|
354 | doHelp();
|
---|
355 | }
|
---|
356 | }
|
---|
357 | } catch (SSHStdIO.CtrlDPressedException e) {
|
---|
358 | retVal = true;
|
---|
359 | } catch (Exception e) {
|
---|
360 | retVal = false;
|
---|
361 | }
|
---|
362 | return retVal;
|
---|
363 | }
|
---|
364 |
|
---|
365 | public void launchCommandShell() {
|
---|
366 | (new Thread(new Runnable() {
|
---|
367 | public void run() {
|
---|
368 | stdio.isConnected = false;
|
---|
369 | if(!doCommandShell()) {
|
---|
370 | stdio.controller.sendDisconnect("exit");
|
---|
371 | } else {
|
---|
372 | stdio.isConnected = true;
|
---|
373 | try {
|
---|
374 | stdio.typedChar((char)0x0c);
|
---|
375 | } catch (IOException e) {
|
---|
376 | // !!!
|
---|
377 | }
|
---|
378 | }
|
---|
379 | }
|
---|
380 | })).start();
|
---|
381 | }
|
---|
382 |
|
---|
383 | public boolean escapeSequenceTyped(char c) {
|
---|
384 | if(c == escapeString.charAt(escapeIdx))
|
---|
385 | escapeIdx++;
|
---|
386 | else
|
---|
387 | escapeIdx = 0;
|
---|
388 | if(escapeIdx == escapeString.length()) {
|
---|
389 | escapeIdx = 0;
|
---|
390 | return true;
|
---|
391 | }
|
---|
392 | return false;
|
---|
393 | }
|
---|
394 |
|
---|
395 | public String escapeString() {
|
---|
396 | return escapeString;
|
---|
397 | }
|
---|
398 |
|
---|
399 | }
|
---|