1 |
efrain |
1 |
<?php
|
|
|
2 |
/**
|
|
|
3 |
* An XML-RPC server
|
|
|
4 |
*
|
|
|
5 |
* @author Donal McMullan donal@catalyst.net.nz
|
|
|
6 |
* @version 0.0.1
|
|
|
7 |
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
|
|
8 |
* @package mnet
|
|
|
9 |
*/
|
|
|
10 |
|
|
|
11 |
// Make certain that config.php doesn't display any errors, and that it doesn't
|
|
|
12 |
// override our do-not-display-errors setting:
|
|
|
13 |
// disable moodle specific debug messages and any errors in output
|
|
|
14 |
define('NO_DEBUG_DISPLAY', true);
|
|
|
15 |
// cookies are not used, makes sure there is empty global $USER
|
|
|
16 |
define('NO_MOODLE_COOKIES', true);
|
|
|
17 |
|
|
|
18 |
define('MNET_SERVER', true);
|
|
|
19 |
|
|
|
20 |
require(__DIR__.'/../../config.php');
|
|
|
21 |
|
|
|
22 |
$mnet = get_mnet_environment();
|
|
|
23 |
// Include MNET stuff:
|
|
|
24 |
require_once $CFG->dirroot.'/mnet/lib.php';
|
|
|
25 |
require_once $CFG->dirroot.'/mnet/remote_client.php';
|
|
|
26 |
require_once $CFG->dirroot.'/mnet/xmlrpc/serverlib.php';
|
|
|
27 |
|
|
|
28 |
|
|
|
29 |
if ($CFG->mnet_dispatcher_mode === 'off') {
|
|
|
30 |
throw new \moodle_exception('mnetdisabled', 'mnet');
|
|
|
31 |
}
|
|
|
32 |
|
|
|
33 |
// Content type for output is not html:
|
|
|
34 |
header('Content-type: text/xml; charset=utf-8');
|
|
|
35 |
|
|
|
36 |
$rawpostdata = file_get_contents("php://input");
|
|
|
37 |
mnet_debug("RAW POST DATA", 2);
|
|
|
38 |
mnet_debug($rawpostdata, 2);
|
|
|
39 |
|
|
|
40 |
if (!isset($_SERVER)) {
|
|
|
41 |
exit(mnet_server_fault(712, get_string('phperror', 'mnet')));
|
|
|
42 |
}
|
|
|
43 |
|
|
|
44 |
|
|
|
45 |
// New global variable which ONLY gets set in this server page, so you know that
|
|
|
46 |
// if you've been called by a remote Moodle, this should be set:
|
|
|
47 |
$remoteclient = new mnet_remote_client();
|
|
|
48 |
set_mnet_remote_client($remoteclient);
|
|
|
49 |
|
|
|
50 |
try {
|
|
|
51 |
$plaintextmessage = mnet_server_strip_encryption($rawpostdata);
|
|
|
52 |
$xmlrpcrequest = mnet_server_strip_signature($plaintextmessage);
|
|
|
53 |
} catch (Exception $e) {
|
|
|
54 |
mnet_debug('encryption strip exception thrown: ' . $e->getMessage());
|
|
|
55 |
exit(mnet_server_fault($e->getCode(), $e->getMessage(), $e->a));
|
|
|
56 |
}
|
|
|
57 |
|
|
|
58 |
mnet_debug('XMLRPC Payload', 2);
|
|
|
59 |
mnet_debug($xmlrpcrequest, 2);
|
|
|
60 |
|
|
|
61 |
if($remoteclient->pushkey == true) {
|
|
|
62 |
// The peer used one of our older public keys, we will return a
|
|
|
63 |
// signed/encrypted error message containing our new public key
|
|
|
64 |
// Sign message with our old key, and encrypt to the peer's private key.
|
|
|
65 |
mnet_debug('sending back new key');
|
|
|
66 |
exit(mnet_server_fault_xml(7025, $mnet->public_key, $remoteclient->useprivatekey));
|
|
|
67 |
}
|
|
|
68 |
// Have a peek at what the request would be if we were to process it
|
|
|
69 |
$encoder = new \PhpXmlRpc\Encoder();
|
|
|
70 |
$orequest = $encoder->decodeXML($xmlrpcrequest); // First, to internal.
|
|
|
71 |
$method = $orequest->method(); // We just need the method.
|
|
|
72 |
mnet_debug("incoming mnet request $method");
|
|
|
73 |
|
|
|
74 |
// One of three conditions need to be met before we continue processing this request:
|
|
|
75 |
// 1. Request is properly encrypted and signed
|
|
|
76 |
// 2. Request is for a keyswap (we don't mind enencrypted or unsigned requests for a public key)
|
|
|
77 |
// 3. Request is properly signed and we're happy with it being unencrypted
|
|
|
78 |
if ((($remoteclient->request_was_encrypted == true) && ($remoteclient->signatureok == true))
|
|
|
79 |
|| (($method == 'system.keyswap') || ($method == 'system/keyswap'))
|
|
|
80 |
|| (($remoteclient->signatureok == true) && ($remoteclient->plaintext_is_ok() == true))) {
|
|
|
81 |
try {
|
|
|
82 |
// main dispatch call. will echo the response directly
|
|
|
83 |
mnet_server_dispatch($xmlrpcrequest);
|
|
|
84 |
mnet_debug('exiting cleanly');
|
|
|
85 |
exit;
|
|
|
86 |
} catch (Exception $e) {
|
|
|
87 |
mnet_debug('dispatch exception thrown: ' . $e->getMessage());
|
|
|
88 |
exit(mnet_server_fault($e->getCode(), $e->getMessage(), $e->a));
|
|
|
89 |
}
|
|
|
90 |
}
|
|
|
91 |
// if we get to here, something is wrong
|
|
|
92 |
// so detect a few common cases and send appropriate errors
|
|
|
93 |
if (($remoteclient->request_was_encrypted == false) && ($remoteclient->plaintext_is_ok() == false)) {
|
|
|
94 |
mnet_debug('non encrypted request');
|
|
|
95 |
exit(mnet_server_fault(7021, get_string('forbidden-transport', 'mnet')));
|
|
|
96 |
}
|
|
|
97 |
|
|
|
98 |
if ($remoteclient->request_was_signed == false) {
|
|
|
99 |
// Request was not signed
|
|
|
100 |
mnet_debug('non signed request');
|
|
|
101 |
exit(mnet_server_fault(711, get_string('verifysignature-error', 'mnet')));
|
|
|
102 |
}
|
|
|
103 |
|
|
|
104 |
if ($remoteclient->signatureok == false) {
|
|
|
105 |
// We were unable to verify the signature
|
|
|
106 |
mnet_debug('non verified signature');
|
|
|
107 |
exit(mnet_server_fault(710, get_string('verifysignature-invalid', 'mnet')));
|
|
|
108 |
}
|
|
|
109 |
mnet_debug('unknown error');
|
|
|
110 |
exit(mnet_server_fault(7000, get_string('unknownerror', 'mnet')));
|