Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Michel-Lemieux2003-08-11 15:57:18 -0400
committerJean Michel-Lemieux2003-08-11 15:57:18 -0400
commitd8c5f1efc046d5ad92b88cae64560f189d661a4b (patch)
tree78e2ce765b597f9203451e648d3981acaa691f90
parent632a8c93bb36e46b27a95a5479714ef597032e36 (diff)
downloadeclipse.platform.team-d8c5f1efc046d5ad92b88cae64560f189d661a4b.tar.gz
eclipse.platform.team-d8c5f1efc046d5ad92b88cae64560f189d661a4b.tar.xz
eclipse.platform.team-d8c5f1efc046d5ad92b88cae64560f189d661a4b.zip
Bug 41161: [Sync View] Can cause CVS client to lock SSH account due to invalid password attemps
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java34
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java34
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java26
-rw-r--r--bundles/org.eclipse.team.cvs.ssh/src/org/eclipse/team/internal/ccvs/ssh/Client.java37
4 files changed, 89 insertions, 42 deletions
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java
index 8266afa8e..26b61275c 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java
@@ -34,6 +34,7 @@ public class PollingInputStream extends FilterInputStream {
private static final boolean DEBUG = Policy.DEBUG_STREAMS;
private int numAttempts;
private IProgressMonitor monitor;
+ private boolean cancellable;
/**
* Creates a new polling input stream.
@@ -46,6 +47,7 @@ public class PollingInputStream extends FilterInputStream {
super(in);
this.numAttempts = numAttempts;
this.monitor = monitor;
+ this.cancellable = true;
}
/**
@@ -72,7 +74,7 @@ public class PollingInputStream extends FilterInputStream {
in.close();
return;
} catch (InterruptedIOException e) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
if (++attempts == numAttempts)
throw new InterruptedIOException(Policy.bind("PollingInputStream.closeTimeout")); //$NON-NLS-1$
if (DEBUG) System.out.println("close retry=" + attempts); //$NON-NLS-1$
@@ -91,7 +93,7 @@ public class PollingInputStream extends FilterInputStream {
public int read() throws IOException {
int attempts = 0;
for (;;) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
try {
return in.read();
} catch (InterruptedIOException e) {
@@ -112,7 +114,7 @@ public class PollingInputStream extends FilterInputStream {
public int read(byte[] buffer, int off, int len) throws IOException {
int attempts = 0;
for (;;) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
try {
return in.read(buffer, off, len);
} catch (InterruptedIOException e) {
@@ -134,7 +136,7 @@ public class PollingInputStream extends FilterInputStream {
public long skip(long count) throws IOException {
int attempts = 0;
for (;;) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
try {
return in.skip(count);
} catch (InterruptedIOException e) {
@@ -159,4 +161,28 @@ public class PollingInputStream extends FilterInputStream {
if (in.read(buffer, 0, available) < 1) break;
}
}
+
+ /**
+ * Called to set whether cancellation will be checked by this stream. Turning cancellation checking
+ * off can be very useful for protecting critical portions of a protocol that shouldn't be interrupted.
+ * For example, it is often necessary to protect login sequences.
+ * @param cancellable a flag controlling whether this stream will check for cancellation.
+ */
+ public void setIsCancellable(boolean cancellable) {
+ this.cancellable = cancellable;
+ }
+
+ /**
+ * Checked whether the monitor for this stream has been cancelled. If the cancellable
+ * flag is <code>false</code> then the monitor is never cancelled.
+ * @return <code>true</code> if the monitor has been cancelled and <code>false</code>
+ * otherwise.
+ */
+ private boolean checkCancellation() {
+ if(cancellable) {
+ return monitor.isCanceled();
+ } else {
+ return false;
+ }
+ }
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java
index 985357eba..ecbdb8eeb 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java
@@ -32,6 +32,7 @@ public class PollingOutputStream extends FilterOutputStream {
private static final boolean DEBUG = Policy.DEBUG_STREAMS;
private int numAttempts;
private IProgressMonitor monitor;
+ private boolean cancellable;
/**
* Creates a new polling output stream.
@@ -44,6 +45,7 @@ public class PollingOutputStream extends FilterOutputStream {
super(out);
this.numAttempts = numAttempts;
this.monitor = monitor;
+ this.cancellable = true;
}
/**
@@ -56,7 +58,7 @@ public class PollingOutputStream extends FilterOutputStream {
public void write(int b) throws IOException {
int attempts = 0;
for (;;) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
try {
out.write(b);
return;
@@ -79,7 +81,7 @@ public class PollingOutputStream extends FilterOutputStream {
int count = 0;
int attempts = 0;
for (;;) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
try {
out.write(buffer, off, len);
return;
@@ -113,7 +115,7 @@ public class PollingOutputStream extends FilterOutputStream {
int count = 0;
int attempts = 0;
for (;;) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
try {
out.flush();
return;
@@ -151,7 +153,7 @@ public class PollingOutputStream extends FilterOutputStream {
out.close();
return;
} catch (InterruptedIOException e) {
- if (monitor.isCanceled()) throw new OperationCanceledException();
+ if (checkCancellation()) throw new OperationCanceledException();
if (++attempts == numAttempts)
throw new InterruptedIOException(Policy.bind("PollingOutputStream.closeTimeout")); //$NON-NLS-1$
if (DEBUG) System.out.println("close retry=" + attempts); //$NON-NLS-1$
@@ -159,4 +161,28 @@ public class PollingOutputStream extends FilterOutputStream {
}
}
}
+
+ /**
+ * Called to set whether cancellation will be checked by this stream. Turning cancellation checking
+ * off can be very useful for protecting critical portions of a protocol that shouldn't be interrupted.
+ * For example, it is often necessary to protect login sequences.
+ * @param cancellable a flag controlling whether this stream will check for cancellation.
+ */
+ public void setIsCancellable(boolean cancellable) {
+ this.cancellable = cancellable;
+ }
+
+ /**
+ * Checked whether the monitor for this stream has been cancelled. If the cancellable
+ * flag is <code>false</code> then the monitor is never cancelled.
+ * @return <code>true</code> if the monitor has been cancelled and <code>false</code>
+ * otherwise.
+ */
+ private boolean checkCancellation() {
+ if(cancellable) {
+ return monitor.isCanceled();
+ } else {
+ return false;
+ }
+ }
}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java
index 3b0d60c9c..a5d3bb2c8 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java
@@ -108,7 +108,6 @@ public class Session {
private int compressionLevel = 0;
private List expansions;
private Collection /* of ICVSFile */ textTransferOverrideSet = null;
- private boolean hasBeenConnected = false;
private Map caseMappings;
// state need to indicate whether
@@ -315,9 +314,10 @@ public class Session {
if (connection != null) throw new IllegalStateException();
monitor = Policy.monitorFor(monitor);
monitor.beginTask(null, 100);
+ boolean opened = false;
+
try {
connection = location.openConnection(Policy.subMonitorFor(monitor, 50));
- hasBeenConnected = true;
ResponseHandler mtHandler = Request.getResponseHandler("MT"); //$NON-NLS-1$
// accept MT messages for all non-standard server
@@ -367,18 +367,15 @@ public class Session {
if (CVSProviderPlugin.getPlugin().isDetermineVersionEnabled() && location.getServerPlatform() == CVSRepositoryLocation.UNDETERMINED_PLATFORM) {
Command.VERSION.execute(this, location, Policy.subMonitorFor(monitor, 10));
}
- } catch (CVSException e) {
- // If there is a failure opening, make sure we're closed
- if (connection != null) {
- hasBeenConnected = false;
+ opened = true;
+ } finally {
+ if (connection != null && ! opened) {
try {
close();
} catch (CVSException ex) {
CVSProviderPlugin.log(ex);
}
}
- throw e;
- } finally {
monitor.done();
}
}
@@ -389,16 +386,11 @@ public class Session {
* @throws IllegalStateException if the Session is not in the OPEN state
*/
public void close() throws CVSException {
- if (connection == null) {
- if (hasBeenConnected) {
- throw new IllegalStateException();
- } else {
- return;
- }
+ if (connection != null) {
+ connection.close();
+ connection = null;
+ validRequests = null;
}
- connection.close();
- connection = null;
- validRequests = null;
}
/**
diff --git a/bundles/org.eclipse.team.cvs.ssh/src/org/eclipse/team/internal/ccvs/ssh/Client.java b/bundles/org.eclipse.team.cvs.ssh/src/org/eclipse/team/internal/ccvs/ssh/Client.java
index bb1d18dab..440594c5b 100644
--- a/bundles/org.eclipse.team.cvs.ssh/src/org/eclipse/team/internal/ccvs/ssh/Client.java
+++ b/bundles/org.eclipse.team.cvs.ssh/src/org/eclipse/team/internal/ccvs/ssh/Client.java
@@ -23,6 +23,7 @@ import java.math.BigInteger;
import java.net.Socket;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.team.internal.ccvs.core.connection.CVSAuthenticationException;
import org.eclipse.team.internal.ccvs.core.util.Util;
import org.eclipse.team.internal.core.streams.PollingInputStream;
@@ -86,7 +87,7 @@ public class Client {
private Socket socket;
private InputStream socketIn;
- private OutputStream socketOut;
+ private PollingOutputStream socketOut;
private InputStream is;
private OutputStream os;
private boolean connected = false;
@@ -294,16 +295,6 @@ public class Client {
}
}
}
-public Client(InputStream socketIn, OutputStream socketOut, String username, String password) {
- this.socketIn = socketIn;
- this.socketOut = socketOut;
- this.username = username;
- this.password = password;
-}
-public Client(InputStream socketIn, OutputStream socketOut, String username, String password, String command) {
- this(socketIn, socketOut, username, password);
- this.command = command;
-}
public Client(String host, int port, String username, String password) {
this.host = host;
this.port = port;
@@ -360,7 +351,7 @@ public void connect(IProgressMonitor monitor) throws IOException, CVSAuthenticat
// Otherwise, set up the connection
try {
-
+ PollingInputStream pollingInputStream = null;
// Create the socket (the socket should always be null here)
if (socket == null) {
try {
@@ -375,8 +366,10 @@ public void connect(IProgressMonitor monitor) throws IOException, CVSAuthenticat
if (timeout >= 0) {
socket.setSoTimeout(1000);
}
- socketIn = new BufferedInputStream(new PollingInputStream(socket.getInputStream(),
- timeout > 0 ? timeout : 1, monitor));
+ pollingInputStream = new PollingInputStream(socket.getInputStream(),
+ timeout > 0 ? timeout : 1, monitor);
+ socketIn = new BufferedInputStream(pollingInputStream);
+
socketOut = new PollingOutputStream(new TimeoutOutputStream(
socket.getOutputStream(), 8192 /*bufferSize*/, 1000 /*writeTimeout*/, 1000 /*closeTimeout*/),
timeout > 0 ? timeout : 1, monitor);
@@ -385,6 +378,11 @@ public void connect(IProgressMonitor monitor) throws IOException, CVSAuthenticat
// read the ssh server id. The socket creation may of failed if the
// server cannot accept our connection request. We don't expect the
// socket to be closed at this point.
+ // Don't allow cancellation during the initial handshake and login since this
+ // can potentially cause the SSH server to think that it is being hacked and
+ // disable the account.
+ socketOut.setIsCancellable(false /* don't allow cancellation */);
+ pollingInputStream.setIsCancellable(false);
StringBuffer buf = new StringBuffer();
int c;
while ((c = socketIn.read()) != '\n') {
@@ -409,6 +407,9 @@ public void connect(IProgressMonitor monitor) throws IOException, CVSAuthenticat
socketOut.flush();
login();
+
+ socketOut.setIsCancellable(true /* allow cancellation */);
+ pollingInputStream.setIsCancellable(true);
// start a shell and enter interactive session or start by
// executing the given command.
@@ -420,7 +421,6 @@ public void connect(IProgressMonitor monitor) throws IOException, CVSAuthenticat
is = new StandardInputStream();
os = new StandardOutputStream();
-
connected = true;
// If an exception occurs while connected, make sure we disconnect before passing the exception on
} finally {
@@ -436,8 +436,11 @@ public void disconnect() throws IOException {
}
if (connected) {
connected = false;
- send(SSH_MSG_DISCONNECT, null);
- cleanup();
+ try {
+ send(SSH_MSG_DISCONNECT, null);
+ } finally {
+ cleanup();
+ }
}
}
public InputStream getInputStream() throws IOException {

Back to the top