on-demand release 4.0dev+
[moodle.git] / mnet / environment.php
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  */
8 class mnet_environment {
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;
20     function init() {
21         global $CFG, $DB;
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);
33         // Unless this is an install/upgrade, generate the SSL keys.
34         if (empty($this->public_key)) {
35             $this->get_keypair();
36         }
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';
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     }
58     function get_keypair() {
59         global $DB, $CFG;
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;
68         $this->keypair = array();
69         $keypair = get_config('mnet', 'openssl');
71         if (!empty($keypair)) {
72             // Explode/Implode is faster than Unserialize/Serialize
73             list($this->keypair['certificate'], $this->keypair['keypair_PEM']) = explode('@@@@@@@@', $keypair);
74         }
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
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             }
91             if(count($this->keypair)) {
92                 $this->keypair['expires'] = $this->public_key_expires;
93                 array_unshift($openssl_history, $this->keypair);
94             }
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             }
104             if(count($openssl_history) > $openssl_generations) {
105                 $openssl_history = array_slice($openssl_history, 0, $openssl_generations);
106             }
108             set_config('openssl_history', serialize($openssl_history), 'mnet');
110             // 3. Generate fresh keys
111             $this->replace_keys();
112         }
113         return true;
114     }
116     function replace_keys() {
117         global $DB, $CFG;
119         $keypair = mnet_generate_keypair();
120         if (empty($keypair)) {
121             error_log('Can not generate keypair, sorry');
122             return;
123         }
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'];
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         }
145         set_config('openssl', implode('@@@@@@@@', $this->keypair), 'mnet');
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     }
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     }
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     }