2009-11-01 12:22:45 +00:00
|
|
|
<?php
|
2007-01-04 02:33:51 +00:00
|
|
|
/**
|
|
|
|
* Info about the local environment, wrt RPC
|
|
|
|
*
|
|
|
|
* This should really be a singleton. A PHP5 Todo I guess.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class mnet_environment {
|
|
|
|
|
|
|
|
var $id = 0;
|
|
|
|
var $wwwroot = '';
|
|
|
|
var $ip_address = '';
|
|
|
|
var $public_key = '';
|
|
|
|
var $public_key_expires = 0;
|
|
|
|
var $last_connect_time = 0;
|
|
|
|
var $last_log_id = 0;
|
|
|
|
var $keypair = array();
|
2007-01-04 03:33:14 +00:00
|
|
|
var $deleted = 0;
|
2007-01-04 02:33:51 +00:00
|
|
|
|
2023-05-08 13:07:18 +07:00
|
|
|
/** @var string mnet host name. */
|
|
|
|
public $name;
|
|
|
|
|
|
|
|
/** @var int mnet host transport. */
|
|
|
|
public $transport;
|
|
|
|
|
|
|
|
/** @var int mnet host port number. */
|
|
|
|
public $portno;
|
|
|
|
|
|
|
|
/** @var int mnet host force theme. */
|
|
|
|
public $force_theme;
|
|
|
|
|
|
|
|
/** @var string mnet host theme. */
|
|
|
|
public $theme;
|
|
|
|
|
|
|
|
/** @var int mnet host application ID. */
|
|
|
|
public $applicationid;
|
|
|
|
|
|
|
|
/** @var int mnet host SSL verification. */
|
|
|
|
public $sslverification;
|
|
|
|
|
2007-01-04 02:33:51 +00:00
|
|
|
function init() {
|
2008-06-05 18:07:41 +00:00
|
|
|
global $CFG, $DB;
|
2007-01-04 02:33:51 +00:00
|
|
|
|
|
|
|
// Bootstrap the object data on first load.
|
2009-01-11 09:41:48 +00:00
|
|
|
if (!$hostobject = $DB->get_record('mnet_host', array('id'=>$CFG->mnet_localhost_id))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$temparr = get_object_vars($hostobject);
|
|
|
|
foreach($temparr as $key => $value) {
|
|
|
|
$this->$key = $value;
|
|
|
|
}
|
|
|
|
unset($hostobject, $temparr);
|
2007-01-04 02:33:51 +00:00
|
|
|
|
2009-01-11 09:41:48 +00:00
|
|
|
// Unless this is an install/upgrade, generate the SSL keys.
|
|
|
|
if (empty($this->public_key)) {
|
|
|
|
$this->get_keypair();
|
2007-01-04 02:33:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// We need to set up a record that represents 'all hosts'. Any rights
|
|
|
|
// granted to this host will be conferred on all hosts.
|
|
|
|
if (empty($CFG->mnet_all_hosts_id) ) {
|
|
|
|
$hostobject = new stdClass();
|
|
|
|
$hostobject->wwwroot = '';
|
|
|
|
$hostobject->ip_address = '';
|
|
|
|
$hostobject->public_key = '';
|
2008-09-18 16:15:21 +00:00
|
|
|
$hostobject->public_key_expires = 0;
|
|
|
|
$hostobject->last_connect_time = 0;
|
|
|
|
$hostobject->last_log_id = 0;
|
2007-01-04 02:33:51 +00:00
|
|
|
$hostobject->deleted = 0;
|
|
|
|
$hostobject->name = 'All Hosts';
|
|
|
|
|
2008-06-05 18:07:41 +00:00
|
|
|
$hostobject->id = $DB->insert_record('mnet_host',$hostobject);
|
2007-01-04 02:33:51 +00:00
|
|
|
set_config('mnet_all_hosts_id', $hostobject->id);
|
|
|
|
$CFG->mnet_all_hosts_id = $hostobject->id;
|
|
|
|
unset($hostobject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function get_keypair() {
|
2009-01-11 09:41:48 +00:00
|
|
|
global $DB, $CFG;
|
2008-06-02 21:39:23 +00:00
|
|
|
|
2007-01-04 03:34:14 +00:00
|
|
|
// We don't generate keys on install/upgrade because we want the USER
|
|
|
|
// record to have an email address, city and country already.
|
2009-06-24 09:17:56 +00:00
|
|
|
if (during_initial_install()) return true;
|
2009-01-11 09:41:48 +00:00
|
|
|
if ($CFG->mnet_dispatcher_mode == 'off') return true;
|
2007-01-05 02:59:14 +00:00
|
|
|
if (!extension_loaded("openssl")) return true;
|
2007-01-04 02:33:51 +00:00
|
|
|
if (!empty($this->keypair)) return true;
|
2007-01-04 03:34:14 +00:00
|
|
|
|
|
|
|
$this->keypair = array();
|
2010-01-11 22:53:11 +00:00
|
|
|
$keypair = get_config('mnet', 'openssl');
|
2007-01-04 03:34:14 +00:00
|
|
|
|
|
|
|
if (!empty($keypair)) {
|
|
|
|
// Explode/Implode is faster than Unserialize/Serialize
|
2007-01-04 03:34:48 +00:00
|
|
|
list($this->keypair['certificate'], $this->keypair['keypair_PEM']) = explode('@@@@@@@@', $keypair);
|
2007-01-04 03:34:14 +00:00
|
|
|
}
|
|
|
|
|
MDL-75645 mnet: Stop caching OpenSSLAsymmetricKey keys
The mnet_environment->keypair array contains the following
elements (and more, just focussing on these):
- keypair_PEM : textual representation of the private key.
- certificate : textual representation of the public key.
- privatekey : OpenSSLAsymmetricKey representation of the private key,
generated from keypair_PEM. See get_private_key().
- publickey : OpenSSLAsymmetricKey representation if the public key,
generated from certificate. See get_public_key().
The last 2 elements in the array are only used as "caching", to avoid
having to call to openssl_pkey_get_private() and
openssl_pkey_get_public() to convert from the textual representation
to the OpenSSLAsymmetricKey representation that is the one required
by a number of openssl functions.
Problems arrive when, as part of the MNet protocol, the mnet_environment
is serialised, because, since PHP 8.0 those OpenSSLAsymmetricKey objects
aren't serialisable any more.
So, as far as they are only used for internal caching it's perfectly ok
to remove the caching bits and use the openssl_pkey_get_xxx() methods
to calculate them under demand.
The alternative to this would be to implement into the mnet_environment
some custom serialisation, skipping those OpenSSLAsymmetricKey
instances, using __sleep(), the Serializabla interface or __serialize(),
but that seems unnecessary because, as explained above, the uses are
really limited and easily replaceable.
That's what this patch does.
2022-09-20 10:49:28 +02:00
|
|
|
if ($this->public_key_expires <= time()) {
|
2007-01-04 03:34:14 +00:00
|
|
|
// Key generation/rotation
|
|
|
|
|
|
|
|
// 1. Archive the current key (if there is one).
|
2010-01-11 22:53:11 +00:00
|
|
|
$result = get_config('mnet', 'openssl_history');
|
2007-01-04 03:34:14 +00:00
|
|
|
if(empty($result)) {
|
|
|
|
set_config('openssl_history', serialize(array()), 'mnet');
|
|
|
|
$openssl_history = array();
|
|
|
|
} else {
|
|
|
|
$openssl_history = unserialize($result);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(count($this->keypair)) {
|
|
|
|
$this->keypair['expires'] = $this->public_key_expires;
|
|
|
|
array_unshift($openssl_history, $this->keypair);
|
|
|
|
}
|
|
|
|
|
2009-11-01 12:22:45 +00:00
|
|
|
// 2. How many old keys do we want to keep? Use array_slice to get
|
2007-01-04 03:34:14 +00:00
|
|
|
// rid of any we don't want
|
2010-01-11 22:53:11 +00:00
|
|
|
$openssl_generations = get_config('mnet', 'openssl_generations');
|
2007-01-04 03:34:14 +00:00
|
|
|
if(empty($openssl_generations)) {
|
|
|
|
set_config('openssl_generations', 3, 'mnet');
|
|
|
|
$openssl_generations = 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(count($openssl_history) > $openssl_generations) {
|
|
|
|
$openssl_history = array_slice($openssl_history, 0, $openssl_generations);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_config('openssl_history', serialize($openssl_history), 'mnet');
|
|
|
|
|
|
|
|
// 3. Generate fresh keys
|
2007-01-04 03:38:30 +00:00
|
|
|
$this->replace_keys();
|
2007-01-04 02:33:51 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-01-04 03:38:30 +00:00
|
|
|
function replace_keys() {
|
2008-06-12 01:16:49 +00:00
|
|
|
global $DB, $CFG;
|
2008-06-05 18:07:41 +00:00
|
|
|
|
2008-11-28 12:54:15 +00:00
|
|
|
$keypair = mnet_generate_keypair();
|
|
|
|
if (empty($keypair)) {
|
|
|
|
error_log('Can not generate keypair, sorry');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-01-04 03:38:30 +00:00
|
|
|
$this->keypair = array();
|
2008-11-28 12:54:15 +00:00
|
|
|
$this->keypair = $keypair;
|
2007-01-04 03:38:30 +00:00
|
|
|
$this->public_key = $this->keypair['certificate'];
|
2007-01-05 03:31:05 +00:00
|
|
|
$details = openssl_x509_parse($this->public_key);
|
2007-01-04 03:38:30 +00:00
|
|
|
$this->public_key_expires = $details['validTo_time_t'];
|
|
|
|
|
2008-06-12 01:16:49 +00:00
|
|
|
$this->wwwroot = $CFG->wwwroot;
|
|
|
|
if (empty($_SERVER['SERVER_ADDR'])) {
|
|
|
|
// SERVER_ADDR is only returned by Apache-like webservers
|
|
|
|
$my_hostname = mnet_get_hostname_from_uri($CFG->wwwroot);
|
|
|
|
$my_ip = gethostbyname($my_hostname); // Returns unmodified hostname on failure. DOH!
|
|
|
|
if ($my_ip == $my_hostname) {
|
|
|
|
$this->ip_address = 'UNKNOWN';
|
|
|
|
} else {
|
|
|
|
$this->ip_address = $my_ip;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$this->ip_address = $_SERVER['SERVER_ADDR'];
|
|
|
|
}
|
|
|
|
|
2007-01-04 03:38:30 +00:00
|
|
|
set_config('openssl', implode('@@@@@@@@', $this->keypair), 'mnet');
|
|
|
|
|
2008-06-05 18:07:41 +00:00
|
|
|
$DB->update_record('mnet_host', $this);
|
MDL-76053 admin: Remove various warnings related to MNet
This partially reverts MDL-73270, where some useful environmental
checks and notifications in the admin UI were added to inform
about different parts of Moodle relying on the "unsupported"
php-xmlrpc extension.
Since then, some changes have happened in core, only available
for Moodle 4.1 and up (see the MDL-70889 mini-epic). Namely:
- MNet (SSO, roaming, auth, enrol and Mahara portfolio) are not
using the php-xmlrpc extension anymore, but a pure php library.
- The xmlrpc webservices protocol, has been move from core to
the plugins directory, although it continues using the php-xmlrpc
extension.
Because of that here we are removing all the checks and notifications
related with MNet (not using the extension anymore), but keeping the
webservice plugin ones (still using the extension). Surely if some day the
protocol stops using the extension, we'll be able to remove the
corresponding checks too. But that's future.
Note the associated lang strings have been also removed (not deprecated)
because they were highly specific and hardly reusable:
- xmlrpcmaharaenabled
- xmlrpcmnetauthenticationenabled
- xmlrpcmnetenabled
And very same applies, because MNet doesn't contain anything deprecated
or not supported anymore, hence, straight deletion, to the function:
- mnet_get_deprecation_notice()
Also, related tests using any of the removed stuff above have been deleted.
In the other side, the "check_xmlrpc_usage" continues existing and
being used both by environment checks and admin notifications but,
as commented above, now it only looks for the xmlrpc webservice
protocol now.
2022-10-27 23:06:52 +02:00
|
|
|
error_log('New public key has been generated. It expires ' . date('Y/m/d h:i:s', $this->public_key_expires));
|
2007-01-04 03:38:30 +00:00
|
|
|
}
|
|
|
|
|
2007-01-04 02:33:51 +00:00
|
|
|
function get_private_key() {
|
|
|
|
if (empty($this->keypair)) $this->get_keypair();
|
MDL-75645 mnet: Stop caching OpenSSLAsymmetricKey keys
The mnet_environment->keypair array contains the following
elements (and more, just focussing on these):
- keypair_PEM : textual representation of the private key.
- certificate : textual representation of the public key.
- privatekey : OpenSSLAsymmetricKey representation of the private key,
generated from keypair_PEM. See get_private_key().
- publickey : OpenSSLAsymmetricKey representation if the public key,
generated from certificate. See get_public_key().
The last 2 elements in the array are only used as "caching", to avoid
having to call to openssl_pkey_get_private() and
openssl_pkey_get_public() to convert from the textual representation
to the OpenSSLAsymmetricKey representation that is the one required
by a number of openssl functions.
Problems arrive when, as part of the MNet protocol, the mnet_environment
is serialised, because, since PHP 8.0 those OpenSSLAsymmetricKey objects
aren't serialisable any more.
So, as far as they are only used for internal caching it's perfectly ok
to remove the caching bits and use the openssl_pkey_get_xxx() methods
to calculate them under demand.
The alternative to this would be to implement into the mnet_environment
some custom serialisation, skipping those OpenSSLAsymmetricKey
instances, using __sleep(), the Serializabla interface or __serialize(),
but that seems unnecessary because, as explained above, the uses are
really limited and easily replaceable.
That's what this patch does.
2022-09-20 10:49:28 +02:00
|
|
|
return openssl_pkey_get_private($this->keypair['keypair_PEM']);
|
2007-01-04 02:33:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function get_public_key() {
|
|
|
|
if (!isset($this->keypair)) $this->get_keypair();
|
MDL-75645 mnet: Stop caching OpenSSLAsymmetricKey keys
The mnet_environment->keypair array contains the following
elements (and more, just focussing on these):
- keypair_PEM : textual representation of the private key.
- certificate : textual representation of the public key.
- privatekey : OpenSSLAsymmetricKey representation of the private key,
generated from keypair_PEM. See get_private_key().
- publickey : OpenSSLAsymmetricKey representation if the public key,
generated from certificate. See get_public_key().
The last 2 elements in the array are only used as "caching", to avoid
having to call to openssl_pkey_get_private() and
openssl_pkey_get_public() to convert from the textual representation
to the OpenSSLAsymmetricKey representation that is the one required
by a number of openssl functions.
Problems arrive when, as part of the MNet protocol, the mnet_environment
is serialised, because, since PHP 8.0 those OpenSSLAsymmetricKey objects
aren't serialisable any more.
So, as far as they are only used for internal caching it's perfectly ok
to remove the caching bits and use the openssl_pkey_get_xxx() methods
to calculate them under demand.
The alternative to this would be to implement into the mnet_environment
some custom serialisation, skipping those OpenSSLAsymmetricKey
instances, using __sleep(), the Serializabla interface or __serialize(),
but that seems unnecessary because, as explained above, the uses are
really limited and easily replaceable.
That's what this patch does.
2022-09-20 10:49:28 +02:00
|
|
|
return openssl_pkey_get_public($this->keypair['certificate']);
|
2007-01-04 02:33:51 +00:00
|
|
|
}
|
|
|
|
}
|