phpseclib\Net\SSH1::_connect PHP Method

_connect() public method

Connect to an SSHv1 server
public _connect ( ) : boolean
return boolean
    function _connect()
    {
        $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
        if (!$this->fsock) {
            throw new \RuntimeException(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"));
        }
        $this->server_identification = $init_line = fgets($this->fsock, 255);
        if (defined('NET_SSH1_LOGGING')) {
            $this->_append_log('<-', $this->server_identification);
            $this->_append_log('->', $this->identifier . "\r\n");
        }
        if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
            throw new \RuntimeException('Can only connect to SSH servers');
        }
        if ($parts[1][0] != 1) {
            throw new \RuntimeException("Cannot connect to {$parts['1']} servers");
        }
        fputs($this->fsock, $this->identifier . "\r\n");
        $response = $this->_get_binary_packet();
        if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
            throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY');
        }
        $anti_spoofing_cookie = Strings::shift($response[self::RESPONSE_DATA], 8);
        Strings::shift($response[self::RESPONSE_DATA], 4);
        if (strlen($response[self::RESPONSE_DATA]) < 2) {
            return false;
        }
        $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2));
        $server_key_public_exponent = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
        $this->server_key_public_exponent = $server_key_public_exponent;
        if (strlen($response[self::RESPONSE_DATA]) < 2) {
            return false;
        }
        $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2));
        $server_key_public_modulus = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
        $this->server_key_public_modulus = $server_key_public_modulus;
        Strings::shift($response[self::RESPONSE_DATA], 4);
        if (strlen($response[self::RESPONSE_DATA]) < 2) {
            return false;
        }
        $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2));
        $host_key_public_exponent = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
        $this->host_key_public_exponent = $host_key_public_exponent;
        if (strlen($response[self::RESPONSE_DATA]) < 2) {
            return false;
        }
        $temp = unpack('nlen', Strings::shift($response[self::RESPONSE_DATA], 2));
        $host_key_public_modulus = new BigInteger(Strings::shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
        $this->host_key_public_modulus = $host_key_public_modulus;
        Strings::shift($response[self::RESPONSE_DATA], 4);
        // get a list of the supported ciphers
        if (strlen($response[self::RESPONSE_DATA]) < 4) {
            return false;
        }
        extract(unpack('Nsupported_ciphers_mask', Strings::shift($response[self::RESPONSE_DATA], 4)));
        foreach ($this->supported_ciphers as $mask => $name) {
            if (($supported_ciphers_mask & 1 << $mask) == 0) {
                unset($this->supported_ciphers[$mask]);
            }
        }
        // get a list of the supported authentications
        if (strlen($response[self::RESPONSE_DATA]) < 4) {
            return false;
        }
        extract(unpack('Nsupported_authentications_mask', Strings::shift($response[self::RESPONSE_DATA], 4)));
        foreach ($this->supported_authentications as $mask => $name) {
            if (($supported_authentications_mask & 1 << $mask) == 0) {
                unset($this->supported_authentications[$mask]);
            }
        }
        $session_id = md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie, true);
        $session_key = Random::string(32);
        $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
        if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
            $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
            $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
        } else {
            $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
            $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
        }
        $cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : self::CIPHER_3DES;
        $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
        if (!$this->_send_binary_packet($data)) {
            throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY');
        }
        switch ($cipher) {
            //case self::CIPHER_NONE:
            //    $this->crypto = new \phpseclib\Crypt\Null();
            //    break;
            case self::CIPHER_DES:
                $this->crypto = new DES(DES::MODE_CBC);
                $this->crypto->disablePadding();
                $this->crypto->enableContinuousBuffer();
                $this->crypto->setKey(substr($session_key, 0, 8));
                // "The iv (initialization vector) is initialized to all zeroes."
                $this->crypto->setIV(str_repeat("", 8));
                break;
            case self::CIPHER_3DES:
                $this->crypto = new TripleDES(TripleDES::MODE_3CBC);
                $this->crypto->disablePadding();
                $this->crypto->enableContinuousBuffer();
                $this->crypto->setKey(substr($session_key, 0, 24));
                // "All three initialization vectors are initialized to zero."
                $this->crypto->setIV(str_repeat("", 8));
                break;
                //case self::CIPHER_RC4:
                //    $this->crypto = new RC4();
                //    $this->crypto->enableContinuousBuffer();
                //    $this->crypto->setKey(substr($session_key, 0,  16));
                //    break;
        }
        $response = $this->_get_binary_packet();
        if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
            throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
        }
        $this->bitmap = self::MASK_CONNECTED;
        return true;
    }