1 /*
2 * SSHTools - Java SSH2 API
3 *
4 * Copyright (C) 2002-2003 Lee David Painter and Contributors.
5 *
6 * Contributions made by:
7 *
8 * Brett Smith
9 * Richard Pernavas
10 * Erwin Bolwidt
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26 package com.sshtools.common.configuration;
27
28 import com.sshtools.common.util.PropertyUtil;
29
30 import com.sshtools.j2ssh.authentication.SshAuthenticationClient;
31 import com.sshtools.j2ssh.authentication.SshAuthenticationClientFactory;
32 import com.sshtools.j2ssh.configuration.SshConnectionProperties;
33 import com.sshtools.j2ssh.forwarding.ForwardingConfiguration;
34 import com.sshtools.j2ssh.io.IOUtil;
35 import com.sshtools.j2ssh.transport.AlgorithmNotSupportedException;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40 import org.xml.sax.Attributes;
41 import org.xml.sax.SAXException;
42 import org.xml.sax.helpers.DefaultHandler;
43
44 import java.awt.Color;
45
46 import java.io.File;
47 import java.io.FileInputStream;
48 import java.io.FileNotFoundException;
49 import java.io.FileOutputStream;
50 import java.io.IOException;
51 import java.io.InputStream;
52
53 import java.util.HashMap;
54 import java.util.Iterator;
55 import java.util.Map;
56 import java.util.Properties;
57
58 import javax.xml.parsers.ParserConfigurationException;
59 import javax.xml.parsers.SAXParser;
60 import javax.xml.parsers.SAXParserFactory;
61
62
63 /**
64 *
65 *
66 * @author $author$
67 * @version $Revision: 1.22 $
68 */
69 public class SshToolsConnectionProfile extends SshConnectionProperties {
70 private static Log log = LogFactory.getLog(SshToolsConnectionProfile.class);
71
72 /** */
73 public static final int DO_NOTHING = 1;
74
75 /** */
76 public static final int START_SHELL = 2;
77
78 /** */
79 public static final int EXECUTE_COMMANDS = 3;
80 private Map applicationProperties = new HashMap();
81 private Map sftpFavorites = new HashMap();
82 private Map authMethods = new HashMap();
83 private boolean requestPseudoTerminal = true;
84 private boolean disconnectOnSessionClose = true;
85 private int onceAuthenticated = START_SHELL;
86 private String executeCommands = "";
87 private boolean allowAgentForwarding = false;
88
89 // SAX Processing variables
90 private String currentElement = null;
91 private String currentAuthentication = null;
92 private Properties currentProperties = null;
93 private String connectionFile;
94
95 /**
96 * Creates a new SshToolsConnectionProfile object.
97 */
98 public SshToolsConnectionProfile() {
99 }
100
101 /**
102 *
103 *
104 * @return
105 */
106 public Map getAuthenticationMethods() {
107 return authMethods;
108 }
109
110 /**
111 *
112 *
113 * @return
114 */
115 public boolean requiresPseudoTerminal() {
116 return requestPseudoTerminal;
117 }
118
119 /**
120 *
121 *
122 * @return
123 */
124 public boolean disconnectOnSessionClose() {
125 return disconnectOnSessionClose;
126 }
127
128 /**
129 *
130 *
131 * @param requiresPseudoTerminal
132 */
133 public void setRequiresPseudoTerminal(boolean requiresPseudoTerminal) {
134 this.requestPseudoTerminal = requiresPseudoTerminal;
135 }
136
137 /**
138 *
139 *
140 * @param disconnectOnSessionClose
141 */
142 public void setDisconnectOnSessionClose(boolean disconnectOnSessionClose) {
143 this.disconnectOnSessionClose = disconnectOnSessionClose;
144 }
145
146 /**
147 *
148 */
149 public void clearAuthenticationCache() {
150 SshAuthenticationClient auth;
151 Properties properties;
152
153 for (Iterator it = authMethods.values().iterator(); it.hasNext();) {
154 auth = (SshAuthenticationClient) it.next();
155 properties = auth.getPersistableProperties();
156 auth.reset();
157 auth.setPersistableProperties(properties);
158 }
159 }
160
161 /**
162 *
163 *
164 * @param onceAuthenticated
165 */
166 public void setOnceAuthenticatedCommand(int onceAuthenticated) {
167 this.onceAuthenticated = onceAuthenticated;
168 }
169
170 /**
171 *
172 *
173 * @return
174 */
175 public int getOnceAuthenticatedCommand() {
176 return onceAuthenticated;
177 }
178
179 /**
180 *
181 *
182 * @param executeCommands
183 */
184 public void setCommandsToExecute(String executeCommands) {
185 this.executeCommands = executeCommands;
186 }
187
188 /**
189 *
190 *
191 * @return
192 */
193 public String getCommandsToExecute() {
194 return executeCommands;
195 }
196
197 /**
198 *
199 *
200 * @param name
201 * @param defaultValue
202 *
203 * @return
204 */
205 public String getApplicationProperty(String name, String defaultValue) {
206 String value = (String) applicationProperties.get(name);
207
208 if (value == null) {
209 return defaultValue;
210 } else {
211 return value;
212 }
213 }
214
215 /**
216 *
217 *
218 * @param name
219 * @param defaultValue
220 *
221 * @return
222 */
223 public Map getSftpFavorites() {
224 return sftpFavorites;
225 }
226
227 /**
228 *
229 *
230 * @param name
231 * @param defaultValue
232 *
233 * @return
234 */
235 public void setSftpFavorite(String name, String value) {
236 sftpFavorites.put(name, value);
237 }
238
239 /**
240 *
241 *
242 * @param name
243 * @param defaultValue
244 *
245 * @return
246 */
247 public int getApplicationPropertyInt(String name, int defaultValue) {
248 try {
249 return Integer.parseInt(getApplicationProperty(name,
250 String.valueOf(defaultValue)));
251 } catch (NumberFormatException nfe) {
252 return defaultValue;
253 }
254 }
255
256 /**
257 *
258 *
259 * @param name
260 * @param defaultValue
261 *
262 * @return
263 */
264 public boolean getApplicationPropertyBoolean(String name,
265 boolean defaultValue) {
266 try {
267 return new Boolean(getApplicationProperty(name,
268 String.valueOf(defaultValue))).booleanValue();
269 } catch (NumberFormatException nfe) {
270 return defaultValue;
271 }
272 }
273
274 /**
275 *
276 *
277 * @param name
278 * @param defaultColor
279 *
280 * @return
281 */
282 public Color getApplicationPropertyColor(String name, Color defaultColor) {
283 return PropertyUtil.stringToColor(getApplicationProperty(name,
284 PropertyUtil.colorToString(defaultColor)));
285 }
286
287 /**
288 *
289 *
290 * @param name
291 * @param value
292 */
293 public void setApplicationProperty(String name, String value) {
294 applicationProperties.put(name, value);
295 }
296
297 /**
298 *
299 *
300 * @param name
301 * @param value
302 */
303 public void setApplicationProperty(String name, int value) {
304 applicationProperties.put(name, String.valueOf(value));
305 }
306
307 /**
308 *
309 *
310 * @param name
311 * @param value
312 */
313 public void setApplicationProperty(String name, boolean value) {
314 applicationProperties.put(name, String.valueOf(value));
315 }
316
317 /**
318 *
319 *
320 * @param name
321 * @param value
322 */
323 public void setApplicationProperty(String name, Color value) {
324 applicationProperties.put(name, PropertyUtil.colorToString(value));
325 }
326
327 /**
328 *
329 *
330 * @param method
331 */
332 public void addAuthenticationMethod(SshAuthenticationClient method) {
333 if (method != null) {
334 if (!authMethods.containsKey(method.getMethodName())) {
335 authMethods.put(method.getMethodName(), method);
336 }
337 }
338 }
339
340 /**
341 *
342 *
343 * @param config
344 */
345 public void addLocalForwarding(ForwardingConfiguration config) {
346 if (config != null) {
347 localForwardings.put(config.getName(), config);
348 }
349 }
350
351 /**
352 *
353 *
354 * @param config
355 */
356 public void addRemoteForwarding(ForwardingConfiguration config) {
357 if (config != null) {
358 remoteForwardings.put(config.getName(), config);
359 }
360 }
361
362 /**
363 *
364 *
365 * @return
366 */
367 public boolean getAllowAgentForwarding() {
368 return allowAgentForwarding;
369 }
370
371 /**
372 *
373 *
374 * @param allowAgentForwarding
375 */
376 public void setAllowAgentForwarding(boolean allowAgentForwarding) {
377 this.allowAgentForwarding = allowAgentForwarding;
378 }
379
380 /**
381 *
382 *
383 * @param name
384 */
385 public void removeLocalForwarding(String name) {
386 localForwardings.remove(name);
387 }
388
389 /**
390 *
391 *
392 * @param name
393 */
394 public void removeRemoteForwarding(String name) {
395 remoteForwardings.remove(name);
396 }
397
398 /**
399 *
400 *
401 * @param file
402 *
403 * @throws InvalidProfileFileException
404 */
405 public void open(String file) throws InvalidProfileFileException {
406 connectionFile = file;
407 open(new File(file));
408 }
409
410 /**
411 *
412 *
413 * @param file
414 *
415 * @throws InvalidProfileFileException
416 */
417 public void open(File file) throws InvalidProfileFileException {
418 InputStream in = null;
419
420 try {
421 in = new FileInputStream(file);
422 open(in);
423 } catch (FileNotFoundException fnfe) {
424 throw new InvalidProfileFileException(file + " was not found!");
425 } finally {
426 IOUtil.closeStream(in);
427 }
428 }
429
430 /**
431 *
432 *
433 * @param in
434 *
435 * @throws InvalidProfileFileException
436 */
437 public void open(InputStream in) throws InvalidProfileFileException {
438 try {
439 SAXParserFactory saxFactory = SAXParserFactory.newInstance();
440 SAXParser saxParser = saxFactory.newSAXParser();
441 XMLHandler handler = new XMLHandler();
442 saxParser.parse(in, handler);
443 handler = null;
444
445 // in.close();
446 } catch (IOException ioe) {
447 throw new InvalidProfileFileException("IO error. " +
448 ioe.getMessage());
449 } catch (SAXException sax) {
450 throw new InvalidProfileFileException("SAX Error: " +
451 sax.getMessage());
452 } catch (ParserConfigurationException pce) {
453 throw new InvalidProfileFileException("SAX Parser Error: " +
454 pce.getMessage());
455 } finally {
456 }
457 }
458
459 /**
460 *
461 *
462 * @param method
463 */
464 public void removeAuthenticaitonMethod(String method) {
465 authMethods.remove(method);
466 }
467
468 public void removeAuthenticationMethods() {
469 authMethods.clear();
470 }
471
472 /**
473 *
474 *
475 * @param file
476 *
477 * @throws InvalidProfileFileException
478 */
479 public void save(String file) throws InvalidProfileFileException {
480 try {
481 File f = new File(file);
482 FileOutputStream out = new FileOutputStream(f);
483 out.write(toString().getBytes());
484 out.close();
485 } catch (FileNotFoundException fnfe) {
486 throw new InvalidProfileFileException(file + " was not found!");
487 } catch (IOException ioe) {
488 throw new InvalidProfileFileException("io error on " + file);
489 } finally {
490 }
491 }
492
493 public void save() throws InvalidProfileFileException {
494 save(connectionFile);
495 }
496
497 /**
498 *
499 *
500 * @return
501 */
502 public String toString() {
503 String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
504 xml += ("<SshToolsConnectionProfile Hostname=\"" + host + "\" Port=\"" +
505 String.valueOf(port) + "\" Username=\"" + username + "\"" +
506 " Provider=\"" + getTransportProviderString() + "\">");
507 xml += (" <PreferedCipher Client2Server=\"" + prefEncryption +
508 "\" Server2Client=\"" + prefDecryption + "\"/>\n");
509 xml += (" <PreferedMac Client2Server=\"" + prefRecvMac +
510 "\" Server2Client=\"" + prefSendMac + "\"/>\n");
511 xml += (" <PreferedCompression Client2Server=\"" + prefRecvComp +
512 "\" Server2Client=\"" + prefSendComp + "\"/>\n");
513 xml += (" <PreferedPublicKey Name=\"" + prefPK + "\"/>\n");
514 xml += (" <PreferedKeyExchange Name=\"" + prefKex + "\"/>\n");
515 xml += (" <OnceAuthenticated value=\"" +
516 String.valueOf(onceAuthenticated) + "\"/>\n");
517
518 if (onceAuthenticated == EXECUTE_COMMANDS) {
519 xml += (" <ExecuteCommands>" + executeCommands +
520 "</ExecuteCommands>\n");
521 }
522
523 Iterator it = authMethods.entrySet().iterator();
524 Map.Entry entry;
525 Properties properties;
526
527 while (it.hasNext()) {
528 entry = (Map.Entry) it.next();
529 xml += (" <AuthenticationMethod Name=\"" + entry.getKey() +
530 "\">\n");
531
532 SshAuthenticationClient auth = (SshAuthenticationClient) entry.getValue();
533 properties = auth.getPersistableProperties();
534
535 Iterator it2 = properties.entrySet().iterator();
536
537 while (it2.hasNext()) {
538 entry = (Map.Entry) it2.next();
539 xml += (" <AuthenticationProperty Name=\"" +
540 entry.getKey() + "\" Value=\"" + entry.getValue() + "\"/>\n");
541 }
542
543 xml += " </AuthenticationMethod>\n";
544 }
545
546 it = applicationProperties.entrySet().iterator();
547
548 while (it.hasNext()) {
549 entry = (Map.Entry) it.next();
550 xml += (" <ApplicationProperty Name=\"" + entry.getKey() +
551 "\" Value=\"" + entry.getValue() + "\"/>\n");
552 }
553
554 // Write the SFTP Favorite entries to file
555 it = sftpFavorites.entrySet().iterator();
556
557 while (it.hasNext()) {
558 entry = (Map.Entry) it.next();
559 xml += (" <SftpFavorite Name=\"" + entry.getKey() +
560 "\" Value=\"" + entry.getValue() + "\"/>\n");
561 }
562
563 it = localForwardings.values().iterator();
564 xml += (" <ForwardingAutoStart value=\"" +
565 String.valueOf(forwardingAutoStart) + "\"/>\n");
566
567 while (it.hasNext()) {
568 ForwardingConfiguration config = (ForwardingConfiguration) it.next();
569 xml += (" <LocalPortForwarding Name=\"" + config.getName() +
570 "\" AddressToBind=\"" + config.getAddressToBind() +
571 "\" PortToBind=\"" + String.valueOf(config.getPortToBind()) +
572 "\" AddressToConnect=\"" + config.getHostToConnect() +
573 "\" PortToConnect=\"" + String.valueOf(config.getPortToConnect()) +
574 "\"/>\n");
575 }
576
577 it = remoteForwardings.values().iterator();
578
579 while (it.hasNext()) {
580 ForwardingConfiguration config = (ForwardingConfiguration) it.next();
581 xml += (" <RemotePortForwarding Name=\"" + config.getName() +
582 "\" AddressToBind=\"" + config.getAddressToBind() +
583 "\" PortToBind=\"" + String.valueOf(config.getPortToBind()) +
584 "\" AddressToConnect=\"" + config.getHostToConnect() +
585 "\" PortToConnect=\"" + String.valueOf(config.getPortToConnect()) +
586 "\"/>\n");
587 }
588
589 xml += "</SshToolsConnectionProfile>";
590
591 return xml;
592 }
593
594 private class XMLHandler extends DefaultHandler {
595 boolean commandsToExecute = false;
596
597 public void startElement(String uri, String localName, String qname,
598 Attributes attrs) throws SAXException {
599 if (currentElement == null) {
600 if (!qname.equals("SshToolsConnectionProfile")) {
601 throw new SAXException("Unexpected root element " + qname);
602 }
603
604 host = attrs.getValue("Hostname");
605 username = attrs.getValue("Username");
606
607 String p = attrs.getValue("Port");
608
609 if (p == null) {
610 port = 22;
611 } else {
612 port = Integer.parseInt(p);
613 }
614
615 setTransportProviderString(attrs.getValue("Provider"));
616
617 if ((host == null) || (username == null)) {
618 throw new SAXException(
619 "Required attribute for element <SshToolsConnectionProfile> missing");
620 }
621 } else {
622 String c2s;
623 String s2c;
624
625 if (currentElement.equals("SshToolsConnectionProfile")) {
626 if (qname.equals("PreferedCipher")) {
627 c2s = attrs.getValue("Client2Server");
628 s2c = attrs.getValue("Server2Client");
629
630 if ((c2s == null) || (s2c == null)) {
631 throw new SAXException(
632 "Required attribute missing for <PreferedCipher> element");
633 }
634
635 prefEncryption = c2s;
636 prefDecryption = s2c;
637 } else if (qname.equals("OnceAuthenticated")) {
638 if (attrs.getValue("value") != null) {
639 try {
640 onceAuthenticated = Integer.parseInt(attrs.getValue(
641 "value"));
642 } catch (NumberFormatException ex) {
643 onceAuthenticated = START_SHELL;
644 }
645 }
646 } else if (qname.equals("ExecuteCommands")) {
647 commandsToExecute = true;
648 executeCommands = "";
649 } else if (qname.equals("PreferedCompression")) {
650 c2s = attrs.getValue("Client2Server");
651 s2c = attrs.getValue("Server2Client");
652
653 if ((c2s == null) || (s2c == null)) {
654 throw new SAXException(
655 "Required attribute missing for <PreferedCompression> element");
656 }
657
658 prefRecvComp = c2s;
659 prefSendComp = s2c;
660 } else if (qname.equals("PreferedMac")) {
661 c2s = attrs.getValue("Client2Server");
662 s2c = attrs.getValue("Server2Client");
663
664 if ((c2s == null) || (s2c == null)) {
665 throw new SAXException(
666 "Required attribute missing for <PreferedMac> element");
667 }
668
669 prefRecvMac = c2s;
670 prefSendMac = s2c;
671 } else if (qname.equals("PreferedPublicKey")) {
672 String name = attrs.getValue("Name");
673
674 if (name == null) {
675 throw new SAXException(
676 "Required attribute missing for <PreferedPublickey> element");
677 }
678
679 prefPK = name;
680 } else if (qname.equals("PreferedKeyExchange")) {
681 String name = attrs.getValue("Name");
682
683 if (name == null) {
684 throw new SAXException(
685 "Required attribute missing for <PreferedKeyExchange> element");
686 }
687
688 prefPK = name;
689 } else if (qname.equals("ApplicationProperty")) {
690 String name = attrs.getValue("Name");
691 String value = attrs.getValue("Value");
692
693 if ((name == null) || (value == null)) {
694 throw new SAXException(
695 "Required attributes missing for <ApplicationProperty> element");
696 }
697
698 applicationProperties.put(name, value);
699 } else if (qname.equals("SftpFavorite")) {
700 String name = attrs.getValue("Name");
701 String value = attrs.getValue("Value");
702
703 if ((name == null) || (value == null)) {
704 throw new SAXException(
705 "Required attributes missing for <SftpFavorite> element");
706 }
707
708 sftpFavorites.put(name, value);
709 } else if (qname.equals("AuthenticationMethod")) {
710 currentAuthentication = attrs.getValue("Name");
711 currentProperties = new Properties();
712
713 if (currentAuthentication == null) {
714 throw new SAXException(
715 "Required attribute missing for <AuthenticationMethod> element");
716 }
717 } else if (qname.equals("LocalPortForwarding") ||
718 qname.equals("RemotePortForwarding")) {
719 String name = attrs.getValue("Name");
720 String addressToBind = attrs.getValue("AddressToBind");
721 String portToBind = attrs.getValue("PortToBind");
722 String addressToConnect = attrs.getValue(
723 "AddressToConnect");
724 String portToConnect = attrs.getValue("PortToConnect");
725
726 if ((name == null) || (addressToBind == null) ||
727 (portToBind == null) ||
728 (addressToConnect == null) ||
729 (portToConnect == null)) {
730 throw new SAXException(
731 "Required attribute missing for <" + qname +
732 "> element");
733 }
734
735 ForwardingConfiguration config = new ForwardingConfiguration(name,
736 addressToBind, Integer.parseInt(portToBind),
737 addressToConnect,
738 Integer.parseInt(portToConnect));
739
740 if (qname.equals("LocalPortForwarding")) {
741 localForwardings.put(name, config);
742 } else {
743 remoteForwardings.put(name, config);
744 }
745 } else if (qname.equals("ForwardingAutoStart")) {
746 try {
747 forwardingAutoStart = Boolean.valueOf(attrs.getValue(
748 "value")).booleanValue();
749 } catch (Throwable ex1) {
750 }
751 } else {
752 throw new SAXException("Unexpected element <" + qname +
753 "> after SshToolsConnectionProfile");
754 }
755 } else if (currentElement.equals("AuthenticationMethod")) {
756 if (qname.equals("AuthenticationProperty")) {
757 String name = attrs.getValue("Name");
758 String value = attrs.getValue("Value");
759
760 if ((name == null) || (value == null)) {
761 throw new SAXException(
762 "Required attribute missing for <AuthenticationProperty> element");
763 }
764
765 currentProperties.setProperty(name, value);
766 } else {
767 throw new SAXException("Unexpected element <" + qname +
768 "> found after AuthenticationMethod");
769 }
770 }
771 }
772
773 currentElement = qname;
774 }
775
776 public void characters(char[] ch, int pos, int len) {
777 executeCommands += new String(ch, pos, len);
778 }
779
780 public void endElement(String uri, String localName, String qname)
781 throws SAXException {
782 if (currentElement != null) {
783 if (!currentElement.equals(qname)) {
784 throw new SAXException("Unexpected end element found " +
785 qname);
786 } else if (qname.equals("SshToolsConnectionProfile")) {
787 currentElement = null;
788 } else if (qname.startsWith("Prefered")) {
789 currentElement = "SshToolsConnectionProfile";
790 } else if (qname.equals("OnceAuthenticated")) {
791 currentElement = "SshToolsConnectionProfile";
792 } else if (qname.equals("ExecuteCommands")) {
793 currentElement = "SshToolsConnectionProfile";
794 } else if (qname.equals("ApplicationProperty")) {
795 currentElement = "SshToolsConnectionProfile";
796 } else if (qname.equals("SftpFavorite")) {
797 currentElement = "SshToolsConnectionProfile";
798 } else if (qname.equals("AuthenticationProperty")) {
799 currentElement = "AuthenticationMethod";
800 } else if (qname.equals("LocalPortForwarding") ||
801 qname.equals("RemotePortForwarding") ||
802 qname.equals("ForwardingAutoStart")) {
803 currentElement = "SshToolsConnectionProfile";
804 } else if (qname.equals("AuthenticationMethod")) {
805 currentElement = "SshToolsConnectionProfile";
806
807 try {
808 SshAuthenticationClient auth = SshAuthenticationClientFactory.newInstance(currentAuthentication);
809 auth.setPersistableProperties(currentProperties);
810 authMethods.put(currentAuthentication, auth);
811 } catch (AlgorithmNotSupportedException anse) {
812 log.warn(
813 "AuthenticationMethod element ignored because '" +
814 currentAuthentication +
815 "' authentication is not supported");
816 } finally {
817 currentAuthentication = null;
818 }
819 } else {
820 throw new SAXException("Unexpected end element <" + qname +
821 "> found");
822 }
823 }
824 }
825 }
826 }