[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/phpseclib/phpseclib/phpseclib/System/SSH/ -> Agent.php (source)

   1  <?php
   2  
   3  /**
   4   * Pure-PHP ssh-agent client.
   5   *
   6   * {@internal See http://api.libssh.org/rfc/PROTOCOL.agent}
   7   *
   8   * PHP version 5
   9   *
  10   * Here are some examples of how to use this library:
  11   * <code>
  12   * <?php
  13   *    include 'vendor/autoload.php';
  14   *
  15   *    $agent = new \phpseclib3\System\SSH\Agent();
  16   *
  17   *    $ssh = new \phpseclib3\Net\SSH2('www.domain.tld');
  18   *    if (!$ssh->login('username', $agent)) {
  19   *        exit('Login Failed');
  20   *    }
  21   *
  22   *    echo $ssh->exec('pwd');
  23   *    echo $ssh->exec('ls -la');
  24   * ?>
  25   * </code>
  26   *
  27   * @category  System
  28   * @package   SSH\Agent
  29   * @author    Jim Wigginton <[email protected]>
  30   * @copyright 2014 Jim Wigginton
  31   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  32   * @link      http://phpseclib.sourceforge.net
  33   */
  34  
  35  namespace phpseclib3\System\SSH;
  36  
  37  use phpseclib3\Common\Functions\Strings;
  38  use phpseclib3\Crypt\PublicKeyLoader;
  39  use phpseclib3\Crypt\RSA;
  40  use phpseclib3\Exception\BadConfigurationException;
  41  use phpseclib3\System\SSH\Agent\Identity;
  42  
  43  /**
  44   * Pure-PHP ssh-agent client identity factory
  45   *
  46   * requestIdentities() method pumps out \phpseclib3\System\SSH\Agent\Identity objects
  47   *
  48   * @package SSH\Agent
  49   * @author  Jim Wigginton <[email protected]>
  50   * @access  public
  51   */
  52  class Agent
  53  {
  54      use Common\Traits\ReadBytes;
  55  
  56      // Message numbers
  57  
  58      // to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
  59      const SSH_AGENTC_REQUEST_IDENTITIES = 11;
  60      // this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
  61      const SSH_AGENT_IDENTITIES_ANSWER = 12;
  62      // the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
  63      const SSH_AGENTC_SIGN_REQUEST = 13;
  64      // the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
  65      const SSH_AGENT_SIGN_RESPONSE = 14;
  66  
  67      // Agent forwarding status
  68  
  69      // no forwarding requested and not active
  70      const FORWARD_NONE = 0;
  71      // request agent forwarding when opportune
  72      const FORWARD_REQUEST = 1;
  73      // forwarding has been request and is active
  74      const FORWARD_ACTIVE = 2;
  75  
  76      /**
  77       * Unused
  78       */
  79      const SSH_AGENT_FAILURE = 5;
  80  
  81      /**
  82       * Socket Resource
  83       *
  84       * @var resource
  85       * @access private
  86       */
  87      private $fsock;
  88  
  89      /**
  90       * Agent forwarding status
  91       *
  92       * @var int
  93       * @access private
  94       */
  95      private $forward_status = self::FORWARD_NONE;
  96  
  97      /**
  98       * Buffer for accumulating forwarded authentication
  99       * agent data arriving on SSH data channel destined
 100       * for agent unix socket
 101       *
 102       * @var string
 103       * @access private
 104       */
 105      private $socket_buffer = '';
 106  
 107      /**
 108       * Tracking the number of bytes we are expecting
 109       * to arrive for the agent socket on the SSH data
 110       * channel
 111       *
 112       * @var int
 113       * @access private
 114       */
 115      private $expected_bytes = 0;
 116  
 117      /**
 118       * The current request channel
 119       *
 120       * @var int
 121       * @access private
 122       */
 123      private $request_channel;
 124  
 125      /**
 126       * Default Constructor
 127       *
 128       * @return \phpseclib3\System\SSH\Agent
 129       * @throws \phpseclib3\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found
 130       * @throws \RuntimeException on connection errors
 131       * @access public
 132       */
 133      public function __construct($address = null)
 134      {
 135          if (!$address) {
 136              switch (true) {
 137                  case isset($_SERVER['SSH_AUTH_SOCK']):
 138                      $address = $_SERVER['SSH_AUTH_SOCK'];
 139                      break;
 140                  case isset($_ENV['SSH_AUTH_SOCK']):
 141                      $address = $_ENV['SSH_AUTH_SOCK'];
 142                      break;
 143                  default:
 144                      throw new BadConfigurationException('SSH_AUTH_SOCK not found');
 145              }
 146          }
 147  
 148          $this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
 149          if (!$this->fsock) {
 150              throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)");
 151          }
 152      }
 153  
 154      /**
 155       * Request Identities
 156       *
 157       * See "2.5.2 Requesting a list of protocol 2 keys"
 158       * Returns an array containing zero or more \phpseclib3\System\SSH\Agent\Identity objects
 159       *
 160       * @return array
 161       * @throws \RuntimeException on receipt of unexpected packets
 162       * @access public
 163       */
 164      public function requestIdentities()
 165      {
 166          if (!$this->fsock) {
 167              return [];
 168          }
 169  
 170          $packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
 171          if (strlen($packet) != fputs($this->fsock, $packet)) {
 172              throw new \RuntimeException('Connection closed while requesting identities');
 173          }
 174  
 175          $length = current(unpack('N', $this->readBytes(4)));
 176          $packet = $this->readBytes($length);
 177  
 178          list($type, $keyCount) = Strings::unpackSSH2('CN', $packet);
 179          if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
 180              throw new \RuntimeException('Unable to request identities');
 181          }
 182  
 183          $identities = [];
 184          for ($i = 0; $i < $keyCount; $i++) {
 185              list($key_blob, $comment) = Strings::unpackSSH2('ss', $packet);
 186              $temp = $key_blob;
 187              list($key_type) = Strings::unpackSSH2('s', $temp);
 188              switch ($key_type) {
 189                  case 'ssh-rsa':
 190                  case 'ssh-dss':
 191                  case 'ssh-ed25519':
 192                  case 'ecdsa-sha2-nistp256':
 193                  case 'ecdsa-sha2-nistp384':
 194                  case 'ecdsa-sha2-nistp521':
 195                      $key = PublicKeyLoader::load($key_type . ' ' . base64_encode($key_blob));
 196              }
 197              // resources are passed by reference by default
 198              if (isset($key)) {
 199                  $identity = (new Identity($this->fsock))
 200                      ->withPublicKey($key)
 201                      ->withPublicKeyBlob($key_blob);
 202                  $identities[] = $identity;
 203                  unset($key);
 204              }
 205          }
 206  
 207          return $identities;
 208      }
 209  
 210      /**
 211       * Signal that agent forwarding should
 212       * be requested when a channel is opened
 213       *
 214       * @return void
 215       * @access public
 216       */
 217      public function startSSHForwarding()
 218      {
 219          if ($this->forward_status == self::FORWARD_NONE) {
 220              $this->forward_status = self::FORWARD_REQUEST;
 221          }
 222      }
 223  
 224      /**
 225       * Request agent forwarding of remote server
 226       *
 227       * @param \phpseclib3\Net\SSH2 $ssh
 228       * @return bool
 229       * @access private
 230       */
 231      private function request_forwarding($ssh)
 232      {
 233          if (!$ssh->requestAgentForwarding()) {
 234              return false;
 235          }
 236  
 237          $this->forward_status = self::FORWARD_ACTIVE;
 238  
 239          return true;
 240      }
 241  
 242      /**
 243       * On successful channel open
 244       *
 245       * This method is called upon successful channel
 246       * open to give the SSH Agent an opportunity
 247       * to take further action. i.e. request agent forwarding
 248       *
 249       * @param \phpseclib3\Net\SSH2 $ssh
 250       * @access private
 251       */
 252      public function registerChannelOpen($ssh)
 253      {
 254          if ($this->forward_status == self::FORWARD_REQUEST) {
 255              $this->request_forwarding($ssh);
 256          }
 257      }
 258  
 259      /**
 260       * Forward data to SSH Agent and return data reply
 261       *
 262       * @param string $data
 263       * @return string Data from SSH Agent
 264       * @throws \RuntimeException on connection errors
 265       * @access public
 266       */
 267      public function forwardData($data)
 268      {
 269          if ($this->expected_bytes > 0) {
 270              $this->socket_buffer .= $data;
 271              $this->expected_bytes -= strlen($data);
 272          } else {
 273              $agent_data_bytes = current(unpack('N', $data));
 274              $current_data_bytes = strlen($data);
 275              $this->socket_buffer = $data;
 276              if ($current_data_bytes != $agent_data_bytes + 4) {
 277                  $this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
 278                  return false;
 279              }
 280          }
 281  
 282          if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
 283              throw new \RuntimeException('Connection closed attempting to forward data to SSH agent');
 284          }
 285  
 286          $this->socket_buffer = '';
 287          $this->expected_bytes = 0;
 288  
 289          $agent_reply_bytes = current(unpack('N', $this->readBytes(4)));
 290  
 291          $agent_reply_data = $this->readBytes($agent_reply_bytes);
 292          $agent_reply_data = current(unpack('a*', $agent_reply_data));
 293  
 294          return pack('Na*', $agent_reply_bytes, $agent_reply_data);
 295      }
 296  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer