Logo Search packages:      
Sourcecode: jenkins-trilead-ssh2 version File versions  Download package

synchronized ConnectionInfo com::trilead::ssh2::Connection::connect ( ServerHostKeyVerifier  verifier,
int  connectTimeout,
int  kexTimeout 
) throws IOException [inline]

Connect to the SSH-2 server and, as soon as the server has presented its host key, use the int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey() method of the verifier to ask for permission to proceed. If verifier is null, then any host key will be accepted - this is NOT recommended, since it makes man-in-the-middle attackes VERY easy (somebody could put a proxy SSH server between you and the real server).

Note: The verifier will be called before doing any crypto calculations (i.e., diffie-hellman). Therefore, if you don't like the presented host key then no CPU cycles are wasted (and the evil server has less information about us).

However, it is still possible that the server presented a fake host key: the server cheated (typically a sign for a man-in-the-middle attack) and is not able to generate a signature that matches its host key. Don't worry, the library will detect such a scenario later when checking the signature (the signature cannot be checked before having completed the diffie-hellman exchange).

Note 2: The int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey() method will *NOT* be called from the current thread, the call is being made from a background thread (there is a background dispatcher thread for every established connection).

Note 3: This method will block as long as the key exchange of the underlying connection has not been completed (and you have not specified any timeouts).

Note 4: If you want to re-use a connection object that was successfully connected, then you must call the close() method before invoking connect() again.

Parameters:
verifierAn object that implements the ServerHostKeyVerifier interface. Pass null to accept any server host key - NOT recommended.
connectTimeoutConnect the underlying TCP socket to the server with the given timeout value (non-negative, in milliseconds). Zero means no timeout. If a proxy is being used (see setProxyData(ProxyData)), then this timeout is used for the connection establishment to the proxy.
kexTimeoutTimeout for complete connection establishment (non-negative, in milliseconds). Zero means no timeout. The timeout counts from the moment you invoke the connect() method and is cancelled as soon as the first key-exchange round has finished. It is possible that the timeout event will be fired during the invocation of the verifier callback, but it will only have an effect after the verifier returns.
Returns:
A ConnectionInfo object containing the details of the established connection.
Exceptions:
IOExceptionIf any problem occurs, e.g., the server's host key is not accepted by the verifier or there is problem during the initial crypto setup (e.g., the signature sent by the server is wrong).

In case of a timeout (either connectTimeout or kexTimeout) a SocketTimeoutException is thrown.

An exception may also be thrown if the connection was already successfully connected (no matter if the connection broke in the mean time) and you invoke connect() again without having called close() first.

If a HTTP proxy is being used and the proxy refuses the connection, then a HTTPProxyException may be thrown, which contains the details returned by the proxy. If the proxy is buggy and does not return a proper HTTP response, then a normal IOException is thrown instead.

Definition at line 631 of file Connection.java.

References com::trilead::ssh2::util::TimeoutService::addTimeoutHandler(), and close().

      {
            final class TimeoutState
            {
                  boolean isCancelled = false;
                  boolean timeoutSocketClosed = false;
            }

            if (tm != null)
                  throw new IOException("Connection to " + hostname + " is already in connected state!");

            if (connectTimeout < 0)
                  throw new IllegalArgumentException("connectTimeout must be non-negative!");

            if (kexTimeout < 0)
                  throw new IllegalArgumentException("kexTimeout must be non-negative!");

            final TimeoutState state = new TimeoutState();

            tm = new TransportManager(hostname, port);

            tm.setConnectionMonitors(connectionMonitors);

            /* Make sure that the runnable below will observe the new value of "tm"
             * and "state" (the runnable will be executed in a different thread, which
             * may be already running, that is why we need a memory barrier here).
             * See also the comment in Channel.java if you
             * are interested in the details.
             * 
             * OKOK, this is paranoid since adding the runnable to the todo list
             * of the TimeoutService will ensure that all writes have been flushed
             * before the Runnable reads anything
             * (there is a synchronized block in TimeoutService.addTimeoutHandler).
             */

            synchronized (tm)
            {
                  /* We could actually synchronize on anything. */
            }

            try
            {
                  TimeoutToken token = null;

                  if (kexTimeout > 0)
                  {
                        final Runnable timeoutHandler = new Runnable()
                        {
                              public void run()
                              {
                                    synchronized (state)
                                    {
                                          if (state.isCancelled)
                                                return;
                                          state.timeoutSocketClosed = true;
                                          tm.close(new SocketTimeoutException("The connect timeout expired"), false);
                                    }
                              }
                        };

                        long timeoutHorizont = System.currentTimeMillis() + kexTimeout;

                        token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler);
                  }

                  try
                  {
                        tm.initialize(cryptoWishList, verifier, dhgexpara, connectTimeout, getOrCreateSecureRND(), proxyData);
                  }
                  catch (SocketTimeoutException se)
                  {
                        throw (SocketTimeoutException) new SocketTimeoutException(
                                    "The connect() operation on the socket timed out.").initCause(se);
                  }

                  tm.setTcpNoDelay(tcpNoDelay);

                  /* Wait until first KEX has finished */

                  ConnectionInfo ci = tm.getConnectionInfo(1);

                  /* Now try to cancel the timeout, if needed */

                  if (token != null)
                  {
                        TimeoutService.cancelTimeoutHandler(token);

                        /* Were we too late? */

                        synchronized (state)
                        {
                              if (state.timeoutSocketClosed)
                                    throw new IOException("This exception will be replaced by the one below =)");
                              /* Just in case the "cancelTimeoutHandler" invocation came just a little bit
                               * too late but the handler did not enter the semaphore yet - we can
                               * still stop it.
                               */
                              state.isCancelled = true;
                        }
                  }

                  return ci;
            }
            catch (SocketTimeoutException ste)
            {
                  throw ste;
            }
            catch (IOException e1)
            {
                  /* This will also invoke any registered connection monitors */
                  close(new Throwable("There was a problem during connect."), false);

                  synchronized (state)
                  {
                        /* Show a clean exception, not something like "the socket is closed!?!" */
                        if (state.timeoutSocketClosed)
                              throw new SocketTimeoutException("The kexTimeout (" + kexTimeout + " ms) expired.");
                  }

                  /* Do not wrap a HTTPProxyException */
                  if (e1 instanceof HTTPProxyException)
                        throw e1;

                  throw (IOException) new IOException("There was a problem while connecting to " + hostname + ":" + port)
                              .initCause(e1);
            }
      }

Here is the call graph for this function:


Generated by  Doxygen 1.6.0   Back to index