Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

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

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