phpseclib\Net\SFTP::login PHP Method

login() public method

Login
public login ( string $username ) : boolean
$username string
return boolean
    function login($username)
    {
        $args = func_get_args();
        if (!call_user_func_array(array(&$this, '_login'), $args)) {
            return false;
        }
        $this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
        $packet = pack('CNa*N3', NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', self::CHANNEL, $this->window_size, 0x4000);
        if (!$this->_send_binary_packet($packet)) {
            return false;
        }
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
        $response = $this->_get_channel_packet(self::CHANNEL);
        if ($response === false) {
            return false;
        }
        $packet = pack('CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp');
        if (!$this->_send_binary_packet($packet)) {
            return false;
        }
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
        $response = $this->_get_channel_packet(self::CHANNEL);
        if ($response === false) {
            // from PuTTY's psftp.exe
            $command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" . "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" . "exec sftp-server";
            // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
            // is redundant
            $packet = pack('CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], strlen('exec'), 'exec', 1, strlen($command), $command);
            if (!$this->_send_binary_packet($packet)) {
                return false;
            }
            $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
            $response = $this->_get_channel_packet(self::CHANNEL);
            if ($response === false) {
                return false;
            }
        }
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
        if (!$this->_send_sftp_packet(NET_SFTP_INIT, "")) {
            return false;
        }
        $response = $this->_get_sftp_packet();
        if ($this->packet_type != NET_SFTP_VERSION) {
            throw new \UnexpectedValueException('Expected SSH_FXP_VERSION');
        }
        if (strlen($response) < 4) {
            return false;
        }
        extract(unpack('Nversion', Strings::shift($response, 4)));
        $this->version = $version;
        while (!empty($response)) {
            if (strlen($response) < 4) {
                return false;
            }
            extract(unpack('Nlength', Strings::shift($response, 4)));
            $key = Strings::shift($response, $length);
            if (strlen($response) < 4) {
                return false;
            }
            extract(unpack('Nlength', Strings::shift($response, 4)));
            $value = Strings::shift($response, $length);
            $this->extensions[$key] = $value;
        }
        /*
         SFTPv4+ defines a 'newline' extension.  SFTPv3 seems to have unofficial support for it via '[email protected]',
         however, I'm not sure what '[email protected]' is supposed to do (the fact that it's unofficial means that it's
         not in the official SFTPv3 specs) and '[email protected]' / 'newline' are likely not drop-in substitutes for
         one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
         '[email protected]' would.
        */
        /*
        if (isset($this->extensions['[email protected]'])) {
            $this->extensions['newline'] = $this->extensions['[email protected]'];
            unset($this->extensions['[email protected]']);
        }
        */
        $this->request_id = 1;
        /*
         A Note on SFTPv4/5/6 support:
         <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
        
         "If the client wishes to interoperate with servers that support noncontiguous version
          numbers it SHOULD send '3'"
        
         Given that the server only sends its version number after the client has already done so, the above
         seems to be suggesting that v3 should be the default version.  This makes sense given that v3 is the
         most popular.
        
         <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
        
         "If the server did not send the "versions" extension, or the version-from-list was not included, the
          server MAY send a status response describing the failure, but MUST then close the channel without
          processing any further requests."
        
         So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
         a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4?  If it only implements
         v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
         in draft-ietf-secsh-filexfer-13 would be quite impossible.  As such, what \phpseclib\Net\SFTP would do is close the
         channel and reopen it with a new and updated SSH_FXP_INIT packet.
        */
        switch ($this->version) {
            case 2:
            case 3:
                break;
            default:
                return false;
        }
        $this->pwd = $this->_realpath('.');
        $this->_update_stat_cache($this->pwd, array());
        return true;
    }

Usage Example

Example #1
1
 /**
  * @return bool
  */
 public function login()
 {
     $password = $this->password;
     $username = $this->username;
     // try to login using ssh key
     if (null === $password) {
         try {
             // try with agent (suppress stupid phpseclib warnings/errors)
             $agent = @new Agent();
         } catch (\Exception $e) {
             $agent = null;
         }
         if ($success = $this->sftp->login($username, $agent)) {
             return true;
         }
         // try with key manually
         $identityFilePath = $_SERVER['HOME'] . '/.ssh/id_rsa';
         if (!is_file($identityFilePath)) {
             $this->io->write(sprintf('Public key file not found in %s', $identityFilePath));
             return false;
         }
         $identityFile = file_get_contents($identityFilePath);
         $key = new RSA();
         $loaded = $key->loadKey($identityFile);
         // first try without keypass
         if (!$loaded || false === ($success = $this->sftp->login($username, $key))) {
             $attempts = 3;
             // now N attempts to load the identity file
             while ($attempts--) {
                 // retry with password
                 $this->keyPassword = $this->keyPassword ?: $this->io->askAndHideAnswer(sprintf('Enter passphrase for %s: ', $identityFilePath));
                 $key->setPassword($this->keyPassword);
                 $loaded = $key->loadKey($identityFile);
                 if (!$loaded) {
                     if ($attempts > 0) {
                         $this->keyPassword = null;
                         $this->io->write('Permission denied, please try again.');
                     }
                 } else {
                     if (false === ($success = $this->sftp->login($username, $key))) {
                         $this->io->write(sprintf('%s@%s: Permission denied (publickey)', $this->username, $this->host));
                     }
                     return $success;
                 }
             }
         }
         return $success;
     }
     // login with given password
     return $this->sftp->login($username, $password);
 }
All Usage Examples Of phpseclib\Net\SFTP::login