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.hosts;
027:
028: import com.sshtools.j2ssh.transport.AbstractKnownHostsKeyVerification;
029: import com.sshtools.j2ssh.transport.InvalidHostFileException;
030: import com.sshtools.j2ssh.transport.TransportProtocolException;
031: import com.sshtools.j2ssh.transport.publickey.SshPublicKey;
032:
033: import java.awt.Component;
034:
035: import java.io.File;
036:
037: import java.lang.reflect.InvocationTargetException;
038:
039: import javax.swing.JOptionPane;
040: import javax.swing.SwingUtilities;
041:
042: /**
043: *
044: *
045: * @author $author$
046: * @version $Revision: 1.13 $
047: */
048: public class DialogKnownHostsKeyVerification extends
049: AbstractKnownHostsKeyVerification {
050: Component parent;
051: private boolean verificationEnabled = true;
052:
053: /**
054: * Creates a new DialogKnownHostsKeyVerification object.
055: *
056: * @param parent
057: *
058: * @throws InvalidHostFileException
059: */
060: public DialogKnownHostsKeyVerification(Component parent)
061: throws InvalidHostFileException {
062: super (new File(System.getProperty("user.home"), ".ssh"
063: + File.separator + "known_hosts").getAbsolutePath());
064: this .parent = parent;
065: }
066:
067: /**
068: * Creates a new DialogKnownHostsKeyVerification object.
069: *
070: * @param parent
071: * @param hostFileName
072: *
073: * @throws InvalidHostFileException
074: */
075: public DialogKnownHostsKeyVerification(Component parent,
076: String hostFileName) throws InvalidHostFileException {
077: super (hostFileName);
078: this .parent = parent;
079: }
080:
081: /**
082: *
083: *
084: * @param enabled
085: */
086: public void setVerificationEnabled(boolean enabled) {
087: this .verificationEnabled = verificationEnabled;
088: }
089:
090: /**
091: *
092: *
093: * @param host
094: *
095: * @throws TransportProtocolException
096: */
097: public void onDeniedHost(final String host)
098: throws TransportProtocolException {
099: // Show a message to the user to inform them that the host
100: // is denied
101: try {
102: if (verificationEnabled) {
103: SwingUtilities.invokeAndWait(new Runnable() {
104: public void run() {
105: JOptionPane
106: .showMessageDialog(
107: parent,
108: "Access to '"
109: + host
110: + "' is denied.\n"
111: + "Verify the access granted/denied in the allowed hosts file.",
112: "Remote Host Authentication",
113: JOptionPane.ERROR_MESSAGE);
114: }
115: });
116: }
117: } catch (InvocationTargetException ite) {
118: throw new TransportProtocolException(
119: "Invocation Exception: " + ite.getMessage());
120: } catch (InterruptedException ie) {
121: throw new TransportProtocolException(
122: "SwingUtilities thread interrupted!");
123: }
124: }
125:
126: /**
127: *
128: *
129: * @param host
130: * @param recorded
131: * @param actual
132: *
133: * @throws TransportProtocolException
134: */
135: public void onHostKeyMismatch(final String host,
136: final SshPublicKey recorded, final SshPublicKey actual)
137: throws TransportProtocolException {
138: try {
139: if (verificationEnabled) {
140: SwingUtilities.invokeAndWait(new Runnable() {
141: public void run() {
142: Object[] options = getOptions();
143: int res = JOptionPane
144: .showOptionDialog(
145: parent,
146: "The host '"
147: + host
148: + "' has provided a different host key.\nThe host key"
149: + " fingerprint provided is '"
150: + actual
151: .getFingerprint()
152: + "'.\n"
153: + "The allowed host key fingerprint is "
154: + recorded
155: .getFingerprint()
156: + ".\nDo you want to allow this host?",
157: "Remote host authentication",
158: JOptionPane.YES_NO_CANCEL_OPTION,
159: JOptionPane.QUESTION_MESSAGE,
160: null, options, options[0]);
161:
162: try {
163: // Handle the reply
164: if ((options.length == 3) && (res == 0)) {
165: // Always allow the host with the new fingerprint
166: allowHost(host, actual, true);
167: } else if (((options.length == 2) && (res == 0))
168: || ((options.length == 3) && (res == 1))) {
169: // Only allow the host this once
170: allowHost(host, actual, false);
171: }
172: } catch (InvalidHostFileException e) {
173: showExceptionMessage(e);
174: }
175: }
176: });
177: }
178: } catch (InvocationTargetException ite) {
179: throw new TransportProtocolException(
180: "Invocation Exception: " + ite.getMessage());
181: } catch (InterruptedException ie) {
182: throw new TransportProtocolException(
183: "SwingUtilities thread interrupted!");
184: }
185: }
186:
187: /**
188: *
189: *
190: * @param host
191: * @param key
192: *
193: * @throws TransportProtocolException
194: */
195: public void onUnknownHost(final String host, final SshPublicKey key)
196: throws TransportProtocolException {
197: // Set up the users options. Only allow always if we can
198: // write to the hosts file
199: try {
200: if (verificationEnabled) {
201: SwingUtilities.invokeAndWait(new Runnable() {
202: public void run() {
203: Object[] options = getOptions();
204: int res = JOptionPane
205: .showOptionDialog(
206: parent,
207: "The host '"
208: + host
209: + "' is unknown. The host key"
210: + " fingerprint is\n'"
211: + key.getFingerprint()
212: + "'.\nDo you want to allow this host?",
213: "Remote host authentication",
214: JOptionPane.YES_NO_CANCEL_OPTION,
215: JOptionPane.QUESTION_MESSAGE,
216: null, options, options[0]);
217:
218: try {
219: // Handle the reply
220: if ((options.length == 3) && (res == 0)) {
221: // Always allow the host with the new fingerprint
222: allowHost(host, key, true);
223: } else if (((options.length == 2) && (res == 0))
224: || ((options.length == 3) && (res == 1))) {
225: // Only allow the host this once
226: allowHost(host, key, false);
227: }
228: } catch (InvalidHostFileException e) {
229: showExceptionMessage(e);
230: }
231: }
232: });
233: }
234: } catch (InvocationTargetException ite) {
235: throw new TransportProtocolException(
236: "Invocation Exception: " + ite.getMessage());
237: } catch (InterruptedException ie) {
238: throw new TransportProtocolException(
239: "SwingUtilities thread interrupted!");
240: }
241: }
242:
243: private String[] getOptions() {
244: return isHostFileWriteable() ? new String[] { "Always", "Yes",
245: "No" } : new String[] { "Yes", "No" };
246: }
247:
248: private void showExceptionMessage(Exception e) {
249: JOptionPane.showMessageDialog(parent,
250: "An unexpected error occured!\n\n" + e.getMessage(),
251: "Host Verification", JOptionPane.ERROR_MESSAGE);
252: }
253: }
|