Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  /**
   3   * Info about the local environment, wrt RPC
   4   *
   5   * This should really be a singleton. A PHP5 Todo I guess.
   6   */
   7  
   8  class mnet_environment {
   9  
  10      var $id                 = 0;
  11      var $wwwroot            = '';
  12      var $ip_address         = '';
  13      var $public_key         = '';
  14      var $public_key_expires = 0;
  15      var $last_connect_time  = 0;
  16      var $last_log_id        = 0;
  17      var $keypair            = array();
  18      var $deleted            = 0;
  19  
  20      function init() {
  21          global $CFG, $DB;
  22  
  23          // Bootstrap the object data on first load.
  24          if (!$hostobject = $DB->get_record('mnet_host', array('id'=>$CFG->mnet_localhost_id))) {
  25              return false;
  26          }
  27          $temparr = get_object_vars($hostobject);
  28          foreach($temparr as $key => $value) {
  29              $this->$key = $value;
  30          }
  31          unset($hostobject, $temparr);
  32  
  33          // Unless this is an install/upgrade, generate the SSL keys.
  34          if (empty($this->public_key)) {
  35              $this->get_keypair();
  36          }
  37  
  38          // We need to set up a record that represents 'all hosts'. Any rights
  39          // granted to this host will be conferred on all hosts.
  40          if (empty($CFG->mnet_all_hosts_id) ) {
  41              $hostobject                     = new stdClass();
  42              $hostobject->wwwroot            = '';
  43              $hostobject->ip_address         = '';
  44              $hostobject->public_key         = '';
  45              $hostobject->public_key_expires = 0;
  46              $hostobject->last_connect_time  = 0;
  47              $hostobject->last_log_id        = 0;
  48              $hostobject->deleted            = 0;
  49              $hostobject->name               = 'All Hosts';
  50  
  51              $hostobject->id = $DB->insert_record('mnet_host',$hostobject);
  52              set_config('mnet_all_hosts_id', $hostobject->id);
  53              $CFG->mnet_all_hosts_id = $hostobject->id;
  54              unset($hostobject);
  55          }
  56      }
  57  
  58      function get_keypair() {
  59          global $DB, $CFG;
  60  
  61          // We don't generate keys on install/upgrade because we want the USER
  62          // record to have an email address, city and country already.
  63          if (during_initial_install()) return true;
  64          if ($CFG->mnet_dispatcher_mode == 'off') return true;
  65          if (!extension_loaded("openssl")) return true;
  66          if (!empty($this->keypair)) return true;
  67  
  68          $this->keypair = array();
  69          $keypair = get_config('mnet', 'openssl');
  70  
  71          if (!empty($keypair)) {
  72              // Explode/Implode is faster than Unserialize/Serialize
  73              list($this->keypair['certificate'], $this->keypair['keypair_PEM']) = explode('@@@@@@@@', $keypair);
  74          }
  75  
  76          if ($this->public_key_expires > time()) {
  77              $this->keypair['privatekey'] = openssl_pkey_get_private($this->keypair['keypair_PEM']);
  78              $this->keypair['publickey']  = openssl_pkey_get_public($this->keypair['certificate']);
  79          } else {
  80              // Key generation/rotation
  81  
  82              // 1. Archive the current key (if there is one).
  83              $result = get_config('mnet', 'openssl_history');
  84              if(empty($result)) {
  85                  set_config('openssl_history', serialize(array()), 'mnet');
  86                  $openssl_history = array();
  87              } else {
  88                  $openssl_history = unserialize($result);
  89              }
  90  
  91              if(count($this->keypair)) {
  92                  $this->keypair['expires'] = $this->public_key_expires;
  93                  array_unshift($openssl_history, $this->keypair);
  94              }
  95  
  96              // 2. How many old keys do we want to keep? Use array_slice to get
  97              // rid of any we don't want
  98              $openssl_generations = get_config('mnet', 'openssl_generations');
  99              if(empty($openssl_generations)) {
 100                  set_config('openssl_generations', 3, 'mnet');
 101                  $openssl_generations = 3;
 102              }
 103  
 104              if(count($openssl_history) > $openssl_generations) {
 105                  $openssl_history = array_slice($openssl_history, 0, $openssl_generations);
 106              }
 107  
 108              set_config('openssl_history', serialize($openssl_history), 'mnet');
 109  
 110              // 3. Generate fresh keys
 111              $this->replace_keys();
 112          }
 113          return true;
 114      }
 115  
 116      function replace_keys() {
 117          global $DB, $CFG;
 118  
 119          $keypair = mnet_generate_keypair();
 120          if (empty($keypair)) {
 121              error_log('Can not generate keypair, sorry');
 122              return;
 123          }
 124  
 125          $this->keypair = array();
 126          $this->keypair            = $keypair;
 127          $this->public_key         = $this->keypair['certificate'];
 128          $details                  = openssl_x509_parse($this->public_key);
 129          $this->public_key_expires = $details['validTo_time_t'];
 130  
 131          $this->wwwroot            = $CFG->wwwroot;
 132          if (empty($_SERVER['SERVER_ADDR'])) {
 133              // SERVER_ADDR is only returned by Apache-like webservers
 134              $my_hostname = mnet_get_hostname_from_uri($CFG->wwwroot);
 135              $my_ip       = gethostbyname($my_hostname);  // Returns unmodified hostname on failure. DOH!
 136              if ($my_ip == $my_hostname) {
 137                  $this->ip_address = 'UNKNOWN';
 138              } else {
 139                  $this->ip_address = $my_ip;
 140              }
 141          } else {
 142              $this->ip_address = $_SERVER['SERVER_ADDR'];
 143          }
 144  
 145          set_config('openssl', implode('@@@@@@@@', $this->keypair), 'mnet');
 146  
 147          $DB->update_record('mnet_host', $this);
 148          error_log('New public key has been generated. It expires ' . date('Y/m/d h:i:s', $this->public_key_expires));
 149      }
 150  
 151      function get_private_key() {
 152          if (empty($this->keypair)) $this->get_keypair();
 153          if (isset($this->keypair['privatekey'])) return $this->keypair['privatekey'];
 154          $this->keypair['privatekey'] = openssl_pkey_get_private($this->keypair['keypair_PEM']);
 155          return $this->keypair['privatekey'];
 156      }
 157  
 158      function get_public_key() {
 159          if (!isset($this->keypair)) $this->get_keypair();
 160          if (isset($this->keypair['publickey'])) return $this->keypair['publickey'];
 161          $this->keypair['publickey'] = openssl_pkey_get_public($this->keypair['certificate']);
 162          return $this->keypair['publickey'];
 163      }
 164  }