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