gluon-web-remote

Web remote Administration for big size of gluon routers
git clone git://archive.git.mtrnord.blog/MTRNord/gluon-web-remote.git
Log | Files | Refs | README

SshConfigFileConfiguration.php (5365B)


      1 <?php
      2 
      3 namespace Ssh;
      4 
      5 use RuntimeException;
      6 
      7 /**
      8  * SSH Config File Configuration
      9  *
     10  * @author Cam Spiers <camspiers@gmail.com>
     11  */
     12 class SshConfigFileConfiguration extends Configuration
     13 {
     14 
     15     const DEFAULT_SSH_IDENTITY = '~/.ssh/id_rsa';
     16 
     17     protected $configs = array();
     18     protected $config;
     19     protected $match = array();
     20 
     21     /**
     22      * Constructor
     23      *
     24      * @param  string  $file
     25      * @param  string  $host
     26      * @param  integer $port
     27      * @param  array   $methods
     28      * @param  array   $callbacks
     29      * @param  string  $identity
     30      */
     31     public function __construct(
     32         $file, $host, $port = 22, array $methods = array(), array $callbacks = array(), $identity = null
     33     )
     34     {
     35         $this->parseSshConfigFile($this->processPath($file));
     36         $this->identity = is_null($identity) ? self::DEFAULT_SSH_IDENTITY : $identity;
     37         $this->config = $this->getConfigForHost($host);
     38 
     39         parent::__construct(
     40             isset($this->config['hostname']) ? $this->config['hostname'] : $host,
     41             isset($this->config['port']) ? $this->config['port'] : $port,
     42             $methods,
     43             $callbacks
     44         );
     45     }
     46 
     47     /**
     48      * Replaces '~'' with users home path
     49      * @param  string $path
     50      * @return string
     51      */
     52     protected function processPath($path)
     53     {
     54         return preg_replace('/^~/', getenv('HOME'), $path);
     55     }
     56 
     57     /**
     58      * Parses the ssh config file into an array of configs for later matching against hosts
     59      * @param  string $file
     60      */
     61     protected function parseSshConfigFile($file)
     62     {
     63         if (!file_exists($file) || !is_readable($file)) {
     64             throw new RuntimeException("The file '$file' does not exist or is not readable");
     65         }
     66         $contents = file_get_contents($file);
     67         $configs = array();
     68         $lineNumber = 1;
     69         foreach (explode(PHP_EOL, $contents) as $line) {
     70             $line = trim($line);
     71             if ($line == '' || $line[0] == '#') {
     72                 continue;
     73             }
     74             $pos = strpos($line, '=');
     75             if ($pos !== false) {
     76                 $key = strtolower(trim(substr($line, 0, $pos)));
     77                 $value = trim(substr($line, $pos + 1, strlen($line)));
     78             } else {
     79                 $i = 0;
     80                 while ($i < strlen($line)) {
     81                     if ($line[$i] == ' ') {
     82                         break;
     83                     }
     84                     $i++;
     85                 }
     86                 if ($i == strlen($line)) {
     87                     throw new RuntimeException("The file '$file' is not parsable at line '$lineNumber'");
     88                 }
     89                 $key = strtolower(trim(substr($line, 0, $i)));
     90                 $value = trim(substr($line, $i + 1, strlen($line)));
     91             }
     92             if ($key == 'host') {
     93                 $this->configs = array_merge($this->configs, $configs);
     94                 $configs = array();
     95                 $hosts = explode(' ', $value);
     96                 foreach ($hosts as $host) {
     97                     $configs[] = array('host' => $host);
     98                 }
     99 
    100             } else {
    101                 foreach ($configs as $host => $config) {
    102                     $configs[$host][$key] = $value;
    103                 }
    104             }
    105             $lineNumber++;
    106         }
    107         $this->configs = array_merge($this->configs, $configs);
    108     }
    109 
    110     /**
    111      * Merges matches of the host in the config file using fnmatch and a length comparison
    112      * @param  string $host
    113      * @return array
    114      */
    115     public function getConfigForHost($host)
    116     {
    117         $matches = array();
    118         foreach ($this->configs as $config) {
    119             if (fnmatch($config['host'], $host)) {
    120                 $matches[] = $config;
    121             }
    122         }
    123         if (count($matches) == 0) {
    124             throw new RuntimeException("Unable to find configuration for host '{$host}'");
    125         }
    126         usort($matches, function ($a, $b) {
    127             return strlen($a['host']) > strlen($b['host']);
    128         });
    129         $result = array();
    130         foreach ($matches as $match) {
    131             $result = array_merge($result, $match);
    132         }
    133         unset($result['host']);
    134         if (isset($result['identityfile'])) {
    135             $result['identityfile'] = $this->processPath($result['identityfile']);
    136         } else if (file_exists($file = $this->processPath($this->getIdentity()))) {
    137             $result['identityfile'] = $file;
    138         }
    139 
    140         return $result;
    141     }
    142 
    143     /**
    144      * Return an authentication mechanism based on the configuration file
    145      * @param  string|null $passphrase
    146      * @param  string|null $user
    147      * @return PublicKeyFile|None
    148      */
    149     public function getAuthentication($passphrase = null, $user = null)
    150     {
    151         if (is_null($user) && !isset($this->config['user'])) {
    152             throw new RuntimeException("Can not authenticate for '{$this->host}' could not find user to authenticate as");
    153         }
    154         $user = $user ?: $this->config['user'];
    155         if (isset($this->config['identityfile'])) {
    156             return new Authentication\PublicKeyFile(
    157                 $user,
    158                 $this->config['identityfile'] . '.pub',
    159                 $this->config['identityfile'],
    160                 $passphrase
    161             );
    162         } else {
    163             return new Authentication\None(
    164                 $user
    165             );
    166         }
    167     }
    168 }