SocksSocketImpl(Proxy proxy) {
   SocketAddress a = proxy.address();
   if (a instanceof InetSocketAddress) {
     InetSocketAddress ad = (InetSocketAddress) a;
     server = ad.getHostName();
     port = ad.getPort();
   }
 }
Ejemplo n.º 2
0
  /**
   * Same as {@link #openConnection()}, except that the connection will be made through the
   * specified proxy; Protocol handlers that do not support proxing will ignore the proxy parameter
   * and make a normal connection.
   *
   * <p>Invoking this method preempts the system's default ProxySelector settings.
   *
   * @param proxy the Proxy through which this connection will be made. If direct connection is
   *     desired, Proxy.NO_PROXY should be specified.
   * @return a <code>URLConnection</code> to the URL.
   * @exception IOException if an I/O exception occurs.
   * @exception SecurityException if a security manager is present and the caller doesn't have
   *     permission to connect to the proxy.
   * @exception IllegalArgumentException will be thrown if proxy is null, or proxy has the wrong
   *     type
   * @exception UnsupportedOperationException if the subclass that implements the protocol handler
   *     doesn't support this method.
   * @see java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
   * @see java.net.URLConnection
   * @see java.net.URLStreamHandler#openConnection(java.net.URL, java.net.Proxy)
   * @since 1.5
   */
  public URLConnection openConnection(Proxy proxy) throws java.io.IOException {
    if (proxy == null) {
      throw new IllegalArgumentException("proxy can not be null");
    }

    SecurityManager sm = System.getSecurityManager();
    if (proxy.type() != Proxy.Type.DIRECT && sm != null) {
      InetSocketAddress epoint = (InetSocketAddress) proxy.address();
      if (epoint.isUnresolved()) sm.checkConnect(epoint.getHostName(), epoint.getPort());
      else sm.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort());
    }
    return handler.openConnection(this, proxy);
  }
Ejemplo n.º 3
0
  private ConnectivitySettings proxyToCs(Proxy proxy, URI uri) {
    ConnectivitySettings cs = new ConnectivitySettings();
    InetSocketAddress isa = (InetSocketAddress) proxy.address();
    switch (proxy.type()) {
      case HTTP:
        setupProxy(cs, ConnectivitySettings.CONNECTION_VIA_HTTPS, isa);
        break;
      case SOCKS:
        setupProxy(cs, ConnectivitySettings.CONNECTION_VIA_SOCKS, isa);
        break;
      default:
    }

    String prosyUser = NetworkSettings.getAuthenticationUsername(uri);
    if (prosyUser != null && !prosyUser.isEmpty()) {
      cs.setProxyUsername(prosyUser);
      cs.setProxyPassword(Keyring.read(NetworkSettings.getKeyForAuthenticationPassword(uri)));
    }
    return cs;
  }
  /**
   * Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind means "accept incoming
   * connection from", so the SocketAddress is the the one of the host we do accept connection from.
   *
   * @param addr the Socket address of the remote host.
   * @exception IOException if an I/O error occurs when binding this socket.
   */
  protected synchronized void socksBind(InetSocketAddress saddr) throws IOException {
    if (socket != null) {
      // this is a client socket, not a server socket, don't
      // call the SOCKS proxy for a bind!
      return;
    }

    // Connects to the SOCKS server

    if (server == null) {
      // This is the general case
      // server is not null only when the socket was created with a
      // specified proxy in which case it does bypass the ProxySelector
      ProxySelector sel =
          (ProxySelector)
              java.security.AccessController.doPrivileged(
                  new java.security.PrivilegedAction() {
                    public Object run() {
                      return ProxySelector.getDefault();
                    }
                  });
      if (sel == null) {
        /*
         * No default proxySelector --> direct connection
         */
        return;
      }
      URI uri = null;
      String host = saddr.getHostName();
      // IPv6 litteral?
      if (saddr.getAddress() instanceof Inet6Address
          && (!host.startsWith("["))
          && (host.indexOf(":") >= 0)) {
        host = "[" + host + "]";
      }
      try {
        uri = new URI("serversocket://" + ParseUtil.encodePath(host) + ":" + saddr.getPort());
      } catch (URISyntaxException e) {
        // This shouldn't happen
        assert false : e;
      }
      Proxy p = null;
      Exception savedExc = null;
      java.util.Iterator<Proxy> iProxy = null;
      iProxy = sel.select(uri).iterator();
      if (iProxy == null || !(iProxy.hasNext())) {
        return;
      }
      while (iProxy.hasNext()) {
        p = iProxy.next();
        if (p == null || p == Proxy.NO_PROXY) {
          return;
        }
        if (p.type() != Proxy.Type.SOCKS)
          throw new SocketException("Unknown proxy type : " + p.type());
        if (!(p.address() instanceof InetSocketAddress))
          throw new SocketException("Unknow address type for proxy: " + p);
        server = ((InetSocketAddress) p.address()).getHostName();
        port = ((InetSocketAddress) p.address()).getPort();

        // Connects to the SOCKS server
        try {
          AccessController.doPrivileged(
              new PrivilegedExceptionAction() {
                public Object run() throws Exception {
                  cmdsock = new Socket(new PlainSocketImpl());
                  cmdsock.connect(new InetSocketAddress(server, port));
                  cmdIn = cmdsock.getInputStream();
                  cmdOut = cmdsock.getOutputStream();
                  return null;
                }
              });
        } catch (Exception e) {
          // Ooops, let's notify the ProxySelector
          sel.connectFailed(uri, p.address(), new SocketException(e.getMessage()));
          server = null;
          port = -1;
          cmdsock = null;
          savedExc = e;
          // Will continue the while loop and try the next proxy
        }
      }

      /*
       * If server is still null at this point, none of the proxy
       * worked
       */
      if (server == null || cmdsock == null) {
        throw new SocketException("Can't connect to SOCKS proxy:" + savedExc.getMessage());
      }
    } else {
      try {
        AccessController.doPrivileged(
            new PrivilegedExceptionAction() {
              public Object run() throws Exception {
                cmdsock = new Socket(new PlainSocketImpl());
                cmdsock.connect(new InetSocketAddress(server, port));
                cmdIn = cmdsock.getInputStream();
                cmdOut = cmdsock.getOutputStream();
                return null;
              }
            });
      } catch (Exception e) {
        throw new SocketException(e.getMessage());
      }
    }
    BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512);
    InputStream in = cmdIn;
    if (useV4) {
      bindV4(in, out, saddr.getAddress(), saddr.getPort());
      return;
    }
    out.write(PROTO_VERS);
    out.write(2);
    out.write(NO_AUTH);
    out.write(USER_PASSW);
    out.flush();
    byte[] data = new byte[2];
    int i = readSocksReply(in, data);
    if (i != 2 || ((int) data[0]) != PROTO_VERS) {
      // Maybe it's not a V5 sever after all
      // Let's try V4 before we give up
      bindV4(in, out, saddr.getAddress(), saddr.getPort());
      return;
    }
    if (((int) data[1]) == NO_METHODS) throw new SocketException("SOCKS : No acceptable methods");
    if (!authenticate(data[1], in, out)) {
      throw new SocketException("SOCKS : authentication failed");
    }
    // We're OK. Let's issue the BIND command.
    out.write(PROTO_VERS);
    out.write(BIND);
    out.write(0);
    int lport = saddr.getPort();
    if (saddr.isUnresolved()) {
      out.write(DOMAIN_NAME);
      out.write(saddr.getHostName().length());
      try {
        out.write(saddr.getHostName().getBytes("ISO-8859-1"));
      } catch (java.io.UnsupportedEncodingException uee) {
        assert false;
      }
      out.write((lport >> 8) & 0xff);
      out.write((lport >> 0) & 0xff);
    } else if (saddr.getAddress() instanceof Inet4Address) {
      byte[] addr1 = saddr.getAddress().getAddress();
      out.write(IPV4);
      out.write(addr1);
      out.write((lport >> 8) & 0xff);
      out.write((lport >> 0) & 0xff);
      out.flush();
    } else if (saddr.getAddress() instanceof Inet6Address) {
      byte[] addr1 = saddr.getAddress().getAddress();
      out.write(IPV6);
      out.write(addr1);
      out.write((lport >> 8) & 0xff);
      out.write((lport >> 0) & 0xff);
      out.flush();
    } else {
      cmdsock.close();
      throw new SocketException("unsupported address type : " + saddr);
    }
    data = new byte[4];
    i = readSocksReply(in, data);
    SocketException ex = null;
    int len, nport;
    byte[] addr;
    switch (data[1]) {
      case REQUEST_OK:
        // success!
        InetSocketAddress real_end = null;
        switch (data[3]) {
          case IPV4:
            addr = new byte[4];
            i = readSocksReply(in, addr);
            if (i != 4) throw new SocketException("Reply from SOCKS server badly formatted");
            data = new byte[2];
            i = readSocksReply(in, data);
            if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted");
            nport = ((int) data[0] & 0xff) << 8;
            nport += ((int) data[1] & 0xff);
            external_address = new InetSocketAddress(new Inet4Address("", addr), nport);
            break;
          case DOMAIN_NAME:
            len = data[1];
            byte[] host = new byte[len];
            i = readSocksReply(in, host);
            if (i != len) throw new SocketException("Reply from SOCKS server badly formatted");
            data = new byte[2];
            i = readSocksReply(in, data);
            if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted");
            nport = ((int) data[0] & 0xff) << 8;
            nport += ((int) data[1] & 0xff);
            external_address = new InetSocketAddress(new String(host), nport);
            break;
          case IPV6:
            len = data[1];
            addr = new byte[len];
            i = readSocksReply(in, addr);
            if (i != len) throw new SocketException("Reply from SOCKS server badly formatted");
            data = new byte[2];
            i = readSocksReply(in, data);
            if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted");
            nport = ((int) data[0] & 0xff) << 8;
            nport += ((int) data[1] & 0xff);
            external_address = new InetSocketAddress(new Inet6Address("", addr), nport);
            break;
        }
        break;
      case GENERAL_FAILURE:
        ex = new SocketException("SOCKS server general failure");
        break;
      case NOT_ALLOWED:
        ex = new SocketException("SOCKS: Bind not allowed by ruleset");
        break;
      case NET_UNREACHABLE:
        ex = new SocketException("SOCKS: Network unreachable");
        break;
      case HOST_UNREACHABLE:
        ex = new SocketException("SOCKS: Host unreachable");
        break;
      case CONN_REFUSED:
        ex = new SocketException("SOCKS: Connection refused");
        break;
      case TTL_EXPIRED:
        ex = new SocketException("SOCKS: TTL expired");
        break;
      case CMD_NOT_SUPPORTED:
        ex = new SocketException("SOCKS: Command not supported");
        break;
      case ADDR_TYPE_NOT_SUP:
        ex = new SocketException("SOCKS: address type not supported");
        break;
    }
    if (ex != null) {
      in.close();
      out.close();
      cmdsock.close();
      cmdsock = null;
      throw ex;
    }
    cmdIn = in;
    cmdOut = out;
  }
  /**
   * Connects the Socks Socket to the specified endpoint. It will first connect to the SOCKS proxy
   * and negotiate the access. If the proxy grants the connections, then the connect is successful
   * and all further traffic will go to the "real" endpoint.
   *
   * @param endpoint the <code>SocketAddress</code> to connect to.
   * @param timeout the timeout value in milliseconds
   * @throws IOException if the connection can't be established.
   * @throws SecurityException if there is a security manager and it doesn't allow the connection
   * @throws IllegalArgumentException if endpoint is null or a SocketAddress subclass not supported
   *     by this socket
   */
  protected void connect(SocketAddress endpoint, int timeout) throws IOException {
    SecurityManager security = System.getSecurityManager();
    if (endpoint == null || !(endpoint instanceof InetSocketAddress))
      throw new IllegalArgumentException("Unsupported address type");
    InetSocketAddress epoint = (InetSocketAddress) endpoint;
    if (security != null) {
      if (epoint.isUnresolved()) security.checkConnect(epoint.getHostName(), epoint.getPort());
      else security.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort());
    }
    if (server == null) {
      // This is the general case
      // server is not null only when the socket was created with a
      // specified proxy in which case it does bypass the ProxySelector
      ProxySelector sel =
          (ProxySelector)
              java.security.AccessController.doPrivileged(
                  new java.security.PrivilegedAction() {
                    public Object run() {
                      return ProxySelector.getDefault();
                    }
                  });
      if (sel == null) {
        /*
         * No default proxySelector --> direct connection
         */
        super.connect(epoint, timeout);
        return;
      }
      URI uri = null;
      String host = epoint.getHostName();
      // IPv6 litteral?
      if (epoint.getAddress() instanceof Inet6Address
          && (!host.startsWith("["))
          && (host.indexOf(":") >= 0)) {
        host = "[" + host + "]";
      }
      try {
        uri = new URI("socket://" + ParseUtil.encodePath(host) + ":" + epoint.getPort());
      } catch (URISyntaxException e) {
        // This shouldn't happen
        assert false : e;
      }
      Proxy p = null;
      IOException savedExc = null;
      java.util.Iterator<Proxy> iProxy = null;
      iProxy = sel.select(uri).iterator();
      if (iProxy == null || !(iProxy.hasNext())) {
        super.connect(epoint, timeout);
        return;
      }
      while (iProxy.hasNext()) {
        p = iProxy.next();
        if (p == null || p == Proxy.NO_PROXY) {
          super.connect(epoint, timeout);
          return;
        }
        if (p.type() != Proxy.Type.SOCKS)
          throw new SocketException("Unknown proxy type : " + p.type());
        if (!(p.address() instanceof InetSocketAddress))
          throw new SocketException("Unknow address type for proxy: " + p);
        server = ((InetSocketAddress) p.address()).getHostName();
        port = ((InetSocketAddress) p.address()).getPort();

        // Connects to the SOCKS server
        try {
          privilegedConnect(server, port, timeout);
          // Worked, let's get outta here
          break;
        } catch (IOException e) {
          // Ooops, let's notify the ProxySelector
          sel.connectFailed(uri, p.address(), e);
          server = null;
          port = -1;
          savedExc = e;
          // Will continue the while loop and try the next proxy
        }
      }

      /*
       * If server is still null at this point, none of the proxy
       * worked
       */
      if (server == null) {
        throw new SocketException("Can't connect to SOCKS proxy:" + savedExc.getMessage());
      }
    } else {
      // Connects to the SOCKS server
      try {
        privilegedConnect(server, port, timeout);
      } catch (IOException e) {
        throw new SocketException(e.getMessage());
      }
    }

    // cmdIn & cmdOut were intialized during the privilegedConnect() call
    BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512);
    InputStream in = cmdIn;

    if (useV4) {
      // SOCKS Protocol version 4 doesn't know how to deal with
      // DOMAIN type of addresses (unresolved addresses here)
      if (epoint.isUnresolved()) throw new UnknownHostException(epoint.toString());
      connectV4(in, out, epoint);
      return;
    }

    // This is SOCKS V5
    out.write(PROTO_VERS);
    out.write(2);
    out.write(NO_AUTH);
    out.write(USER_PASSW);
    out.flush();
    byte[] data = new byte[2];
    int i = readSocksReply(in, data);
    if (i != 2 || ((int) data[0]) != PROTO_VERS) {
      // Maybe it's not a V5 sever after all
      // Let's try V4 before we give up
      // SOCKS Protocol version 4 doesn't know how to deal with
      // DOMAIN type of addresses (unresolved addresses here)
      if (epoint.isUnresolved()) throw new UnknownHostException(epoint.toString());
      connectV4(in, out, epoint);
      return;
    }
    if (((int) data[1]) == NO_METHODS) throw new SocketException("SOCKS : No acceptable methods");
    if (!authenticate(data[1], in, out)) {
      throw new SocketException("SOCKS : authentication failed");
    }
    out.write(PROTO_VERS);
    out.write(CONNECT);
    out.write(0);
    /* Test for IPV4/IPV6/Unresolved */
    if (epoint.isUnresolved()) {
      out.write(DOMAIN_NAME);
      out.write(epoint.getHostName().length());
      try {
        out.write(epoint.getHostName().getBytes("ISO-8859-1"));
      } catch (java.io.UnsupportedEncodingException uee) {
        assert false;
      }
      out.write((epoint.getPort() >> 8) & 0xff);
      out.write((epoint.getPort() >> 0) & 0xff);
    } else if (epoint.getAddress() instanceof Inet6Address) {
      out.write(IPV6);
      out.write(epoint.getAddress().getAddress());
      out.write((epoint.getPort() >> 8) & 0xff);
      out.write((epoint.getPort() >> 0) & 0xff);
    } else {
      out.write(IPV4);
      out.write(epoint.getAddress().getAddress());
      out.write((epoint.getPort() >> 8) & 0xff);
      out.write((epoint.getPort() >> 0) & 0xff);
    }
    out.flush();
    data = new byte[4];
    i = readSocksReply(in, data);
    if (i != 4) throw new SocketException("Reply from SOCKS server has bad length");
    SocketException ex = null;
    int nport, len;
    byte[] addr;
    switch (data[1]) {
      case REQUEST_OK:
        // success!
        switch (data[3]) {
          case IPV4:
            addr = new byte[4];
            i = readSocksReply(in, addr);
            if (i != 4) throw new SocketException("Reply from SOCKS server badly formatted");
            data = new byte[2];
            i = readSocksReply(in, data);
            if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted");
            nport = ((int) data[0] & 0xff) << 8;
            nport += ((int) data[1] & 0xff);
            break;
          case DOMAIN_NAME:
            len = data[1];
            byte[] host = new byte[len];
            i = readSocksReply(in, host);
            if (i != len) throw new SocketException("Reply from SOCKS server badly formatted");
            data = new byte[2];
            i = readSocksReply(in, data);
            if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted");
            nport = ((int) data[0] & 0xff) << 8;
            nport += ((int) data[1] & 0xff);
            break;
          case IPV6:
            len = data[1];
            addr = new byte[len];
            i = readSocksReply(in, addr);
            if (i != len) throw new SocketException("Reply from SOCKS server badly formatted");
            data = new byte[2];
            i = readSocksReply(in, data);
            if (i != 2) throw new SocketException("Reply from SOCKS server badly formatted");
            nport = ((int) data[0] & 0xff) << 8;
            nport += ((int) data[1] & 0xff);
            break;
          default:
            ex = new SocketException("Reply from SOCKS server contains wrong code");
            break;
        }
        break;
      case GENERAL_FAILURE:
        ex = new SocketException("SOCKS server general failure");
        break;
      case NOT_ALLOWED:
        ex = new SocketException("SOCKS: Connection not allowed by ruleset");
        break;
      case NET_UNREACHABLE:
        ex = new SocketException("SOCKS: Network unreachable");
        break;
      case HOST_UNREACHABLE:
        ex = new SocketException("SOCKS: Host unreachable");
        break;
      case CONN_REFUSED:
        ex = new SocketException("SOCKS: Connection refused");
        break;
      case TTL_EXPIRED:
        ex = new SocketException("SOCKS: TTL expired");
        break;
      case CMD_NOT_SUPPORTED:
        ex = new SocketException("SOCKS: Command not supported");
        break;
      case ADDR_TYPE_NOT_SUP:
        ex = new SocketException("SOCKS: address type not supported");
        break;
    }
    if (ex != null) {
      in.close();
      out.close();
      throw ex;
    }
    external_address = epoint;
  }