source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/ssh/SSHTunnelingClient.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 16.6 KB
Line 
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/08/01 22:30:52 $
19 * $Name: rel1-2-1 $
20 *****************************************************************************/
21package mindbright.ssh;
22
23import java.io.IOException;
24import java.io.FileNotFoundException;
25import java.net.UnknownHostException;
26
27import java.awt.*;
28import java.awt.event.*;
29
30import java.io.InputStream;
31import java.io.ByteArrayOutputStream;
32
33import mindbright.application.MindTunnelCli;
34
35import mindbright.util.AWTConvenience;
36
37public class SSHTunnelingClient extends SSHClient implements Runnable, SSHInteractor {
38
39 public static class Logo extends Component {
40 Image logo;
41
42 public Logo(Image logo) {
43 this.logo = logo;
44 }
45
46 public Dimension getMinimumSize() {
47 return getPreferredSize();
48 }
49
50 public Dimension getPreferredSize() {
51 int width = -1;
52 int height = -1;
53 boolean ready = false;
54
55 while (!ready) {
56 width = logo.getWidth(null);
57 height = logo.getHeight(null);
58 if(width != -1 && height != -1) {
59 ready = true;
60 }
61 Thread.yield();
62 }
63 Dimension dim = new Dimension(width, height);
64
65 return dim;
66 }
67
68 public void paint(Graphics g) {
69 if(logo == null)
70 return;
71 Dimension d = getSize();
72 g.drawImage(logo, 0, 0, d.width, d.height, this);
73 }
74 }
75
76 public static final boolean expires = false;
77 public static final boolean licensed = false;
78
79 public static final long validFrom = 965157940452L; // 000801/21:25
80 public static final long validTime = (33L * 24L * 60L * 60L * 1000L);
81
82 public boolean verbose = false;
83 public boolean listMode = false;
84 public boolean haveTunnelDialog = false;
85 public boolean haveSCPDialog = false;
86 public boolean haveProxyDialog = false;
87 public boolean haveServer = false;
88
89 Thread clientThread = null;
90
91 MindTunnelCli tunnelClient;
92
93 Frame parent;
94
95 int logoPlacement;
96
97 SSHPropertyHandler propsHandler;
98
99 public SSHTunnelingClient(SSHPropertyHandler propsHandler, MindTunnelCli tunnelClient) {
100 super(propsHandler, propsHandler);
101
102 this.propsHandler = propsHandler;
103 this.interactor = this; // !!! OUCH
104
105 this.tunnelClient = tunnelClient;
106
107 propsHandler.setInteractor(this);
108 propsHandler.setClient(this);
109 }
110
111 boolean hasExpired() {
112 boolean expired = false;
113 long now = System.currentTimeMillis();
114
115 if(licensed)
116 return false;
117
118 if(expires) {
119 int daysRemaining = (int)((validTime - (now - validFrom)) / (1000L * 60L * 60L * 24L));
120 if(daysRemaining <= 0) {
121 alertDialog("This is a demo version of MindTunnel, it has expired!");
122 expired = true;
123 } else {
124 alertDialog("This is a demo version of MindTunnel, it will expire in " + daysRemaining + " days");
125 }
126 } else {
127 int daysOld = (int)((now - validFrom) / (1000L * 60L * 60L * 24L));
128 alertDialog("This is a demo version of MindTunnel, it is " + daysOld + " days old.");
129 }
130 return expired;
131 }
132
133 public SSHPropertyHandler getPropertyHandler() {
134 return propsHandler;
135 }
136
137 public void run() {
138 clientThread = Thread.currentThread();
139
140 String srv = propsHandler.getProperty("server");
141 if(srv != null && srv.trim().length() != 0) {
142 haveServer = true;
143 }
144
145 showMainWindow();
146
147 if(hasExpired()) {
148 parent.dispose();
149 return;
150 }
151
152 if(NETSCAPE_SECURITY_MODEL) {
153 try {
154 netscape.security.PrivilegeManager.enablePrivilege("TerminalEmulator");
155 } catch (netscape.security.ForbiddenTargetException e) {
156 alertDialog("Full network access denied, normal applet security applies");
157 }
158 }
159
160 while(true) {
161 parent.setTitle(SSH.VER_MINDTUNL + " (offline)");
162 updateButtons();
163
164 if(listMode) {
165 choiceHosts.requestFocus();
166 } else if(haveServer) {
167 textUser.requestFocus();
168 } else {
169 textSrv.requestFocus();
170 }
171
172 try {
173 // This starts a connection to the sshd and all the related stuff...
174 //
175 bootSSH(true);
176
177 parent.setTitle(propsHandler.getProperty("usrname") +
178 "@" + propsHandler.getProperty("server") +
179 " (online)");
180
181 // Tell MindTunnelCli that we are now online
182 //
183 tunnelClient.online();
184
185 // Join main receiver channel thread and wait for session to end
186 //
187 controller.waitForExit();
188
189 } catch(SSHClient.AuthFailException e) {
190 alertDialog(e.getMessage());
191 propsHandler.clearPasswords();
192
193 } catch(UnknownHostException e) {
194 String host = e.getMessage();
195 String msg;
196 if(propsHandler.getProperty("proxytype").equals("none")) {
197 msg = "Unknown host: " + host;
198 } else {
199 msg = "Unknown proxy host: " + host;
200 }
201 alertDialog(msg);
202 propsHandler.clearServerSetting();
203
204 } catch(FileNotFoundException e) {
205 alertDialog("File not found: " + e.getMessage());
206
207 } catch(Exception e) {
208 String msg = e.getMessage();
209 if(msg == null || msg.trim().length() == 0)
210 msg = e.toString();
211 msg = "Error connecting to " + propsHandler.getProperty("server") + ", reason: " + msg;
212 if(SSH.DEBUGMORE) {
213 System.out.println("If an error occured, please send the below stacktrace to [email protected]");
214 e.printStackTrace();
215 }
216 alertDialog(msg);
217
218 } catch(ThreadDeath death) {
219 if(controller != null)
220 controller.killAll();
221 controller = null;
222 throw death;
223 }
224
225 propsHandler.passivateProperties();
226 if(usedOTP) {
227 propsHandler.clearPasswords();
228 }
229 }
230 }
231
232 public void updateButtons() {
233 boolean isConn = isConnected();
234 connBut.setEnabled(!isConn);
235 discBut.setEnabled(isConn);
236 if(listMode) {
237 choiceHosts.setEnabled(!isConn);
238 } else {
239 if(!haveServer)
240 textSrv.setEnabled(!isConn);
241 textUser.setEnabled(!isConn);
242 textPasswd.setEnabled(!isConn);
243 }
244
245 if(tunnelBut != null)
246 tunnelBut.setEnabled(isConn);
247 if(scpBut != null)
248 scpBut.setEnabled(isConn);
249 if(proxyBut != null)
250 proxyBut.setEnabled(!isConn);
251 }
252
253 //
254 // SSHInteractor interface
255 //
256 public void propsStateChanged(SSHPropertyHandler props) {
257 }
258
259 public void startNewSession(SSHClient client) {
260 try {
261 synchronized(this) {
262 this.wait();
263 }
264 } catch (InterruptedException e) {
265 }
266 if(listMode) {
267 try {
268 String host = choiceHosts.getSelectedItem();
269 String pwd = "";
270 do {
271 try {
272 propsHandler.setPropertyPassword(pwd);
273 propsHandler.loadAliasFile(host, false);
274 break;
275 } catch(SSHClient.AuthFailException ee) {
276 }
277 } while((pwd = passwordDialog("Please give file password for " +
278 host, "MindTunnel - File Password")) != null);
279 } catch (Throwable t) {
280 alertDialog("Error loading settings: " + t.getMessage());
281 }
282 } else {
283 if(!haveServer)
284 propsHandler.setProperty("server", textSrv.getText());
285 propsHandler.setProperty("usrname", textUser.getText());
286 String password = textPasswd.getText();
287 propsHandler.setProperty("password", password);
288 propsHandler.setProperty("rsapassword", password);
289 propsHandler.setProperty("tispassword", password);
290 propsHandler.setPropertyPassword(password);
291 textPasswd.setText("");
292 }
293
294 propsHandler.setProperty("forcpty", "false");
295 }
296
297 public void sessionStarted(SSHClient client) {
298 }
299
300 public boolean quietPrompts() {
301 return true;
302 }
303
304 public String promptLine(String prompt, String defaultVal) throws IOException {
305 return null;
306 }
307
308 public String promptPassword(String prompt) throws IOException {
309 String pwd = passwordDialog(prompt, "MindTunnel - Password");
310 if(pwd == null) {
311 throw new IOException("Login canceled by user");
312 }
313 return pwd;
314 }
315
316 public boolean isVerbose() {
317 return verbose;
318 }
319
320 public boolean askConfirmation(String message, boolean defAnswer) {
321 return confirmDialog(message, defAnswer);
322 }
323
324 public void connected(SSHClient client) {
325 }
326
327 public void open(SSHClient client) {
328 updateButtons();
329 }
330
331 public void disconnected(SSHClient client, boolean graceful) {
332 updateButtons();
333 }
334
335 public void report(String msg) {
336 if(verbose) {
337 System.out.println(msg);
338 System.out.println("");
339 }
340 }
341
342 public void alert(String msg) {
343 alertDialog(msg);
344 }
345
346 public void windowClosing(WindowEvent e) {
347 if(!isConnected()) {
348 parent.dispose();
349 clientThread.stop();
350 } else {
351 alertDialog("Please disconnect before exiting!");
352 }
353 }
354
355 Choice choiceHosts;
356 TextField textSrv, textUser, textPasswd;
357 Button connBut, discBut, tunnelBut, scpBut, proxyBut;
358 public final void showMainWindow() {
359 parent = new Frame();
360 parent.addWindowListener(new WindowAdapter() {
361 public void windowClosing(WindowEvent e) { SSHTunnelingClient.this.windowClosing(e); }
362 });
363
364 if(listMode && propsHandler.availableAliases() == null) {
365 listMode = false;
366 alertDialog("Must have home directory with aliases to use list mode");
367 }
368
369 GridBagLayout grid = new GridBagLayout();
370 GridBagConstraints gridc = new GridBagConstraints();
371
372 ActionListener al;
373 Label lbl;
374 Panel p = new Panel();
375
376 p.setLayout(grid);
377
378 gridc.insets = new Insets(4, 4, 4, 4);
379 gridc.fill = GridBagConstraints.HORIZONTAL;
380 gridc.weightx = 1.0;
381 gridc.gridy = 0;
382 gridc.gridwidth = 1;
383 gridc.anchor = GridBagConstraints.WEST;
384
385 String[] l = propsHandler.availableAliases();
386 if(listMode && l != null) {
387 lbl = new Label("SSH Server:");
388 grid.setConstraints(lbl, gridc);
389 p.add(lbl);
390
391 choiceHosts = new Choice();
392 for(int i = 0; i < l.length; i++) {
393 choiceHosts.add(l[i]);
394 }
395 choiceHosts.select(0);
396 grid.setConstraints(choiceHosts, gridc);
397 p.add(choiceHosts);
398 gridc.gridy += 1;
399 } else {
400
401 if(!haveServer) {
402 gridc.weightx = 0;
403 lbl = new Label("Server:");
404 grid.setConstraints(lbl, gridc);
405 p.add(lbl);
406 gridc.gridwidth = GridBagConstraints.REMAINDER;
407 gridc.weightx = 1.0;
408 textSrv = new TextField("", 16);
409 grid.setConstraints(textSrv, gridc);
410 p.add(textSrv);
411 }
412
413 gridc.gridy += 1;
414 gridc.gridwidth = 1;
415 gridc.weightx = 0;
416 lbl = new Label("Username:");
417 grid.setConstraints(lbl, gridc);
418 p.add(lbl);
419 gridc.gridwidth = GridBagConstraints.REMAINDER;
420 gridc.weightx = 1.0;
421 textUser = new TextField("", 16);
422 grid.setConstraints(textUser, gridc);
423 p.add(textUser);
424
425 gridc.gridy += 1;
426 gridc.gridwidth = 1;
427 gridc.weightx = 0;
428 lbl = new Label("Password:");
429 grid.setConstraints(lbl, gridc);
430 p.add(lbl);
431 gridc.gridwidth = GridBagConstraints.REMAINDER;
432 gridc.weightx = 1.0;
433 textPasswd = new TextField("", 16);
434 textPasswd.setEchoChar('*');
435 grid.setConstraints(textPasswd, gridc);
436 p.add(textPasswd);
437
438 if(!haveServer)
439 textSrv.setText(propsHandler.getProperty("server"));
440 textUser.setText(propsHandler.getProperty("usrname"));
441 }
442
443 al = new ActionListener() {
444 public void actionPerformed(ActionEvent e) {
445 if(e.getActionCommand().equals("Connect")) {
446 if(!listMode) {
447 String srv = "dummy";
448 if(!haveServer) {
449 srv = textSrv.getText();
450 }
451 String usr = textUser.getText();
452 if(srv == null || srv.trim().length() == 0 ||
453 usr == null || usr.trim().length() == 0) {
454 return;
455 }
456 }
457 synchronized(SSHTunnelingClient.this) {
458 SSHTunnelingClient.this.notify();
459 }
460 connBut.setEnabled(false);
461 discBut.requestFocus();
462 } else if(e.getActionCommand().equals("Disconnect")) {
463 forcedDisconnect();
464 discBut.setEnabled(false);
465 } else if(e.getActionCommand().equals("Tunnels Setup")) {
466 SSHTunnelDialog.show("MindTunnel - Basic Tunnels Setup",
467 SSHTunnelingClient.this, propsHandler, parent);
468 } else if(e.getActionCommand().equals("File Transfer")) {
469 SSHSCPDialog.show("MindTunnel - File Transfer", parent,
470 propsHandler, SSHTunnelingClient.this);
471 } else if(e.getActionCommand().equals("Configure Proxy")) {
472 SSHProxyDialog.show("MindTunnel - Proxy Settings", parent,
473 propsHandler);
474 }
475 }
476 };
477
478 Panel bp;
479
480 if(haveTunnelDialog || haveSCPDialog || haveProxyDialog) {
481 bp = new Panel(new FlowLayout());
482 if(haveTunnelDialog) {
483 tunnelBut = new Button("Tunnels Setup");
484 tunnelBut.addActionListener(al);
485 bp.add(tunnelBut);
486 }
487 if(haveSCPDialog) {
488 scpBut = new Button("File Transfer");
489 scpBut.addActionListener(al);
490 bp.add(scpBut);
491 }
492 if(haveProxyDialog) {
493 proxyBut = new Button("Configure Proxy");
494 proxyBut.addActionListener(al);
495 bp.add(proxyBut);
496 }
497 gridc.gridy += 1;
498 gridc.gridwidth = GridBagConstraints.REMAINDER;
499 gridc.anchor = GridBagConstraints.CENTER;
500 grid.setConstraints(bp, gridc);
501 p.add(bp);
502 }
503
504 bp = new Panel(new FlowLayout());
505 bp.add(connBut = new Button("Connect"));
506
507 connBut.addActionListener(al);
508
509 bp.add(discBut = new Button("Disconnect"));
510 discBut.addActionListener(al);
511
512 gridc.gridy += 1;
513 gridc.gridwidth = GridBagConstraints.REMAINDER;
514 gridc.anchor = GridBagConstraints.CENTER;
515 grid.setConstraints(bp, gridc);
516 p.add(bp);
517
518 grid = new GridBagLayout();
519 gridc = new GridBagConstraints();
520
521 parent.setLayout(grid);
522
523 gridc.insets = new Insets(4, 4, 4, 4);
524 gridc.gridy = 0;
525 gridc.gridwidth = GridBagConstraints.REMAINDER;
526 gridc.fill = GridBagConstraints.HORIZONTAL;
527 gridc.weightx = 1.0;
528 gridc.anchor = GridBagConstraints.CENTER;
529
530 Image logoImg = getLogo();
531 if(logoImg != null) {
532 Logo logo = new Logo(logoImg);
533 switch(logoPlacement) {
534 case GridBagConstraints.NORTH:
535 gridc.fill = GridBagConstraints.NONE;
536 grid.setConstraints(logo, gridc);
537 parent.add(logo);
538 gridc.fill = GridBagConstraints.HORIZONTAL;
539 gridc.gridy = 1;
540 grid.setConstraints(p, gridc);
541 parent.add(p);
542 break;
543
544 case GridBagConstraints.WEST:
545 gridc.fill = GridBagConstraints.NONE;
546 gridc.gridwidth = 1;
547 grid.setConstraints(logo, gridc);
548 parent.add(logo);
549 gridc.fill = GridBagConstraints.HORIZONTAL;
550 gridc.gridwidth = GridBagConstraints.REMAINDER;
551 grid.setConstraints(p, gridc);
552 parent.add(p);
553 break;
554
555 case GridBagConstraints.EAST:
556 gridc.gridwidth = 1;
557 grid.setConstraints(p, gridc);
558 parent.add(p);
559 gridc.fill = GridBagConstraints.NONE;
560 gridc.gridwidth = GridBagConstraints.REMAINDER;
561 grid.setConstraints(logo, gridc);
562 parent.add(logo);
563 break;
564
565 case GridBagConstraints.SOUTH:
566 grid.setConstraints(p, gridc);
567 parent.add(p);
568 gridc.gridy = 1;
569 gridc.fill = GridBagConstraints.NONE;
570 grid.setConstraints(logo, gridc);
571 parent.add(logo);
572 break;
573 }
574 } else {
575 grid.setConstraints(p, gridc);
576 parent.add(p);
577 }
578
579 AWTConvenience.setKeyListenerOfChildren(parent,
580 new AWTConvenience.OKCancelAdapter(connBut, discBut),
581 null);
582
583 AWTConvenience.setBackgroundOfChildren(parent);
584
585 parent.pack();
586 parent.show();
587 }
588
589 Image getLogo() {
590 InputStream is;
591 ByteArrayOutputStream baos;
592 Image logo = null;
593
594 if((is = this.getClass().getResourceAsStream("/images/logo_top.gif")) != null) {
595 logoPlacement = GridBagConstraints.NORTH;
596 } else if((is = this.getClass().getResourceAsStream("/images/logo_left.gif")) != null) {
597 logoPlacement = GridBagConstraints.WEST;
598 } else if((is = this.getClass().getResourceAsStream("/images/logo_right.gif")) != null) {
599 logoPlacement = GridBagConstraints.EAST;
600 } else if((is = this.getClass().getResourceAsStream("/images/logo_bottom.gif")) != null) {
601 logoPlacement = GridBagConstraints.SOUTH;
602 } else {
603 return null;
604 }
605
606 baos = new ByteArrayOutputStream();
607 try {
608 int c;
609 while((c = is.read()) >= 0)
610 baos.write(c);
611 logo = Toolkit.getDefaultToolkit().createImage(baos.toByteArray());
612 } catch(IOException e) {
613 // !!!
614 }
615
616 return logo;
617 }
618
619 public final boolean confirmDialog(String message, boolean defAnswer) {
620 return SSHMiscDialogs.confirm("MindTunnel - Confirmation", message, true,
621 parent);
622 }
623
624 public final void alertDialog(String message) {
625 SSHMiscDialogs.alert("MindTunnel - Alert", message, parent);
626 }
627
628 public final String passwordDialog(String message, String title) {
629 return SSHMiscDialogs.password(title, message, parent);
630 }
631
632}
Note: See TracBrowser for help on using the repository browser.