<commit_before><?php
/**
 * An XML-RPC server
 *
 * @author  <NAME>  <EMAIL>
 * @version 0.0.1
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
 * @package mnet
 */

// Make certain that config.php doesn't display any errors, and that it doesn't
// override our do-not-display-errors setting:
ini_set('display_errors',0);
require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
ini_set('display_errors',0);

// Include MNET stuff:
require_once $CFG->dirroot.'/mnet/lib.php';
require_once $CFG->dirroot.'/mnet/remote_client.php';

if ($CFG->mnet_dispatcher_mode === 'off') {
    print_error('mnetdisabled', 'mnet');
}

// Content type for output is not html:
header('Content-type: text/xml; charset=utf-8');

// PHP 5.2.2: $HTTP_RAW_POST_DATA not populated bug:
// http://bugs.php.net/bug.php?id=41293
if (empty($HTTP_RAW_POST_DATA)) {
    $HTTP_RAW_POST_DATA = file_get_contents('php://input');
}

if (!empty($CFG->mnet_rpcdebug)) {
    trigger_error("HTTP_RAW_POST_DATA");
    trigger_error($HTTP_RAW_POST_DATA);
}

if (!isset($_SERVER)) {
    exit(mnet_server_fault(712, "phperror"));
}


// New global variable which ONLY gets set in this server page, so you know that
// if you've been called by a remote Moodle, this should be set:
$MNET_REMOTE_CLIENT = new mnet_remote_client();

$plaintextmessage = mnet_server_strip_encryption($HTTP_RAW_POST_DATA);
$xmlrpcrequest = mnet_server_strip_signature($plaintextmessage);

if($MNET_REMOTE_CLIENT->pushkey == true) {
    // The peer used one of our older public keys, we will return a
    // signed/encrypted error message containing our new public key
    // Sign message with our old key, and encrypt to the peer's private key.
    exit(mnet_server_fault_xml(7025, $MNET->public_key, $MNET_REMOTE_CLIENT->useprivatekey));
}
// Have a peek at what the request would be if we were to process it
$params = xmlrpc_decode_request($xmlrpcrequest, $method);

// One of three conditions need to be met before we continue processing this request:
// 1. Request is properly encrypted and signed
// 2. Request is for a keyswap (we don't mind enencrypted or unsigned requests for a public key)
// 3. Request is properly signed and we're happy with it being unencrypted
if ((($MNET_REMOTE_CLIENT->request_was_encrypted == true) && ($MNET_REMOTE_CLIENT->signatureok == true))
    || (($method == 'system.keyswap') || ($method == 'system/keyswap'))
    || (($MNET_REMOTE_CLIENT->signatureok == true) && ($MNET_REMOTE_CLIENT->plaintext_is_ok() == true))) {
    $response = mnet_server_dispatch($xmlrpcrequest);
} else {
    if (($MNET_REMOTE_CLIENT->request_was_encrypted == false) && ($MNET_REMOTE_CLIENT->plaintext_is_ok() == false)) {
        exit(mnet_server_fault(7021, 'forbidden-transport'));
    }

    if ($MNET_REMOTE_CLIENT->request_was_signed == false) {
        // Request was not signed
        exit(mnet_server_fault(711, 'verifysignature-error'));
    }

    if ($MNET_REMOTE_CLIENT->signatureok == false) {
        // We were unable to verify the signature
        exit(mnet_server_fault(710, 'verifysignature-invalid'));
    }
}


if (!empty($CFG->mnet_rpcdebug)) {
    trigger_error("XMLRPC Payload");
    trigger_error(print_r($xmlrpcrequest,1));
}

/**
 * -----XML-Envelope---------------------------------
 * |                                                |
 * |    Encrypted-Symmetric-key----------------     |
 * |    |_____________________________________|     |
 * |                                                |
 * |    Encrypted data-------------------------     |
 * |    |                                     |     |
 * |    |  -XML-Envelope------------------    |     |
 * |    |  |                             |    |     |
 * |    |  |  --Signature-------------   |    |     |
 * |    |  |  |______________________|   |    |     |
 * |    |  |                             |    |     |
 * |    |  |  --Signed-Payload--------   |    |     |
 * |    |  |  |                      |   |    |     |
 * |    |  |  |   XML-RPC Request    |   |    |     |
 * |    |  |  |______________________|   |    |     |
 * |    |  |                             |    |     |
 * |    |  |_____________________________|    |     |
 * |    |_____________________________________|     |
 * |                                                |
 * |________________________________________________|
 *
 */

/* Strip encryption envelope (if present) and decrypt data
 *
 * @param string $HTTP_RAW_POST_DATA The XML that the client sent
 * @return string XML with any encryption envolope removed
 */
function mnet_server_strip_encryption($HTTP_RAW_POST_DATA) {
    global $MNET, $MNET_REMOTE_CLIENT;
    $crypt_parser = new mnet_encxml_parser();
    $crypt_parser->parse($HTTP_RAW_POST_DATA);

    if (!$crypt_parser->payload_encrypted) {
        return $HTTP_RAW_POST_DATA;
    }

    // Make sure we know who we're talking to
    $host_record_exists = $MNET_REMOTE_CLIENT->set_wwwroot($crypt_parser->remote_wwwroot);

    if (false == $host_record_exists) {
        exit(mnet_server_fault(7020, 'wrong-wwwroot', $crypt_parser->remote_wwwroot));
    }

    // This key is symmetric, and is itself encrypted. Can be decrypted using our private key
    $key  = array_pop($crypt_parser->cipher);
    // This data is symmetrically encrypted, can be decrypted using the above key
    $data = array_pop($crypt_parser->cipher);

    $crypt_parser->free_resource();
    $payload          = '';    // Initialize payload var

    //                                          &$payload
    $isOpen = openssl_open(base64_decode($data), $payload, base64_decode($key), $MNET->get_private_key());
    if ($isOpen) {
        $MNET_REMOTE_CLIENT->was_encrypted();
        return $payload;
    }

    // Decryption failed... let's try our archived keys
    $openssl_history = get_config('mnet', 'openssl_history');
    if(empty($openssl_history)) {
        $openssl_history = array();
        set_config('openssl_history', serialize($openssl_history), 'mnet');
    } else {
        $openssl_history = unserialize($openssl_history);
    }
    foreach($openssl_history as $keyset) {
        $keyresource = openssl_pkey_get_private($keyset['keypair_PEM']);
        $isOpen      = openssl_open(base64_decode($data), $payload, base64_decode($key), $keyresource);
        if ($isOpen) {
            // It's an older code, sir, but it checks out

            $MNET_REMOTE_CLIENT->was_encrypted();
            $MNET_REMOTE_CLIENT->encrypted_to($keyresource);
            $MNET_REMOTE_CLIENT->set_pushkey();
            return $payload;
        }
    }

    //If after all that we still couldn't decrypt the message, error out.
    exit(mnet_server_fault(7023, 'encryption-invalid'));
}

/* Strip signature envelope (if present), try to verify any signature using our record of remote peer's public key.
 *
 * @param string $plaintextmessage XML envelope containing XMLRPC request and signature
 * @return string XMLRPC request
 */
function mnet_server_strip_signature($plaintextmessage) {
    global $MNET, $MNET_REMOTE_CLIENT;
    $sig_parser = new mnet_encxml_parser();
    $sig_parser->parse($plaintextmessage);

    if ($sig_parser->signature == '') {
        return $plaintextmessage;
    }

    // Record that the request was signed in some way
    $MNET_REMOTE_CLIENT->was_signed();

    // Load any information we have about this mnet peer
    $MNET_REMOTE_CLIENT->set_wwwroot($crypt_parser->remote_wwwroot);

    $payload = base64_decode($sig_parser->data_object);
    $signature = base64_decode($sig_parser->signature);
    $certificate = $MNET_REMOTE_CLIENT->public_key;

    // If we don't have any certificate for the host, don't try to check the signature
    // Just return the parsed request
    if ($certificate == false) {
        return $payload;
    }

    // Does the signature match the data and the public cert?
    $signature_verified = openssl_verify($payload, $signature, $certificate);
    if ($signature_verified == 0) {
        // $signature was not generated for $payload using $certificate
        // Get the key the remote peer is currently publishing:
        $currkey = mnet_get_public_key($MNET_REMOTE_CLIENT->wwwroot, $MNET_REMOTE_CLIENT->application);
        // If the key the remote peer is currently publishing is different to $certificate
        if($currkey != $certificate) {
            // Try and get the server's new key through trusted means
            $MNET_REMOTE_CLIENT->refresh_key();
            // If we did manage to re-key, try to verify the signature again using the new public key.
            $certificate = $MNET_REMOTE_CLIENT->public_key;<commit_msg>Fixed misnamed variable I believe I was introduced in 1.33<commit_after><?php
/**
 * An XML-RPC server
 *
 * @author  <NAME>  <EMAIL>
 * @version 0.0.1
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
 * @package mnet
 */

// Make certain that config.php doesn't display any errors, and that it doesn't
// override our do-not-display-errors setting:
ini_set('display_errors',0);
require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
ini_set('display_errors',0);

// Include MNET stuff:
require_once $CFG->dirroot.'/mnet/lib.php';
require_once $CFG->dirroot.'/mnet/remote_client.php';

if ($CFG->mnet_dispatcher_mode === 'off') {
    print_error('mnetdisabled', 'mnet');
}

// Content type for output is not html:
header('Content-type: text/xml; charset=utf-8');

// PHP 5.2.2: $HTTP_RAW_POST_DATA not populated bug:
// http://bugs.php.net/bug.php?id=41293
if (empty($HTTP_RAW_POST_DATA)) {
    $HTTP_RAW_POST_DATA = file_get_contents('php://input');
}

if (!empty($CFG->mnet_rpcdebug)) {
    trigger_error("HTTP_RAW_POST_DATA");
    trigger_error($HTTP_RAW_POST_DATA);
}

if (!isset($_SERVER)) {
    exit(mnet_server_fault(712, "phperror"));
}


// New global variable which ONLY gets set in this server page, so you know that
// if you've been called by a remote Moodle, this should be set:
$MNET_REMOTE_CLIENT = new mnet_remote_client();

$plaintextmessage = mnet_server_strip_encryption($HTTP_RAW_POST_DATA);
$xmlrpcrequest = mnet_server_strip_signature($plaintextmessage);

if($MNET_REMOTE_CLIENT->pushkey == true) {
    // The peer used one of our older public keys, we will return a
    // signed/encrypted error message containing our new public key
    // Sign message with our old key, and encrypt to the peer's private key.
    exit(mnet_server_fault_xml(7025, $MNET->public_key, $MNET_REMOTE_CLIENT->useprivatekey));
}
// Have a peek at what the request would be if we were to process it
$params = xmlrpc_decode_request($xmlrpcrequest, $method);

// One of three conditions need to be met before we continue processing this request:
// 1. Request is properly encrypted and signed
// 2. Request is for a keyswap (we don't mind enencrypted or unsigned requests for a public key)
// 3. Request is properly signed and we're happy with it being unencrypted
if ((($MNET_REMOTE_CLIENT->request_was_encrypted == true) && ($MNET_REMOTE_CLIENT->signatureok == true))
    || (($method == 'system.keyswap') || ($method == 'system/keyswap'))
    || (($MNET_REMOTE_CLIENT->signatureok == true) && ($MNET_REMOTE_CLIENT->plaintext_is_ok() == true))) {
    $response = mnet_server_dispatch($xmlrpcrequest);
} else {
    if (($MNET_REMOTE_CLIENT->request_was_encrypted == false) && ($MNET_REMOTE_CLIENT->plaintext_is_ok() == false)) {
        exit(mnet_server_fault(7021, 'forbidden-transport'));
    }

    if ($MNET_REMOTE_CLIENT->request_was_signed == false) {
        // Request was not signed
        exit(mnet_server_fault(711, 'verifysignature-error'));
    }

    if ($MNET_REMOTE_CLIENT->signatureok == false) {
        // We were unable to verify the signature
        exit(mnet_server_fault(710, 'verifysignature-invalid'));
    }
}


if (!empty($CFG->mnet_rpcdebug)) {
    trigger_error("XMLRPC Payload");
    trigger_error(print_r($xmlrpcrequest,1));
}

/**
 * -----XML-Envelope---------------------------------
 * |                                                |
 * |    Encrypted-Symmetric-key----------------     |
 * |    |_____________________________________|     |
 * |                                                |
 * |    Encrypted data-------------------------     |
 * |    |                                     |     |
 * |    |  -XML-Envelope------------------    |     |
 * |    |  |                             |    |     |
 * |    |  |  --Signature-------------   |    |     |
 * |    |  |  |______________________|   |    |     |
 * |    |  |                             |    |     |
 * |    |  |  --Signed-Payload--------   |    |     |
 * |    |  |  |                      |   |    |     |
 * |    |  |  |   XML-RPC Request    |   |    |     |
 * |    |  |  |______________________|   |    |     |
 * |    |  |                             |    |     |
 * |    |  |_____________________________|    |     |
 * |    |_____________________________________|     |
 * |                                                |
 * |________________________________________________|
 *
 */

/* Strip encryption envelope (if present) and decrypt data
 *
 * @param string $HTTP_RAW_POST_DATA The XML that the client sent
 * @return string XML with any encryption envolope removed
 */
function mnet_server_strip_encryption($HTTP_RAW_POST_DATA) {
    global $MNET, $MNET_REMOTE_CLIENT;
    $crypt_parser = new mnet_encxml_parser();
    $crypt_parser->parse($HTTP_RAW_POST_DATA);

    if (!$crypt_parser->payload_encrypted) {
        return $HTTP_RAW_POST_DATA;
    }

    // Make sure we know who we're talking to
    $host_record_exists = $MNET_REMOTE_CLIENT->set_wwwroot($crypt_parser->remote_wwwroot);

    if (false == $host_record_exists) {
        exit(mnet_server_fault(7020, 'wrong-wwwroot', $crypt_parser->remote_wwwroot));
    }

    // This key is symmetric, and is itself encrypted. Can be decrypted using our private key
    $key  = array_pop($crypt_parser->cipher);
    // This data is symmetrically encrypted, can be decrypted using the above key
    $data = array_pop($crypt_parser->cipher);

    $crypt_parser->free_resource();
    $payload          = '';    // Initialize payload var

    //                                          &$payload
    $isOpen = openssl_open(base64_decode($data), $payload, base64_decode($key), $MNET->get_private_key());
    if ($isOpen) {
        $MNET_REMOTE_CLIENT->was_encrypted();
        return $payload;
    }

    // Decryption failed... let's try our archived keys
    $openssl_history = get_config('mnet', 'openssl_history');
    if(empty($openssl_history)) {
        $openssl_history = array();
        set_config('openssl_history', serialize($openssl_history), 'mnet');
    } else {
        $openssl_history = unserialize($openssl_history);
    }
    foreach($openssl_history as $keyset) {
        $keyresource = openssl_pkey_get_private($keyset['keypair_PEM']);
        $isOpen      = openssl_open(base64_decode($data), $payload, base64_decode($key), $keyresource);
        if ($isOpen) {
            // It's an older code, sir, but it checks out

            $MNET_REMOTE_CLIENT->was_encrypted();
            $MNET_REMOTE_CLIENT->encrypted_to($keyresource);
            $MNET_REMOTE_CLIENT->set_pushkey();
            return $payload;
        }
    }

    //If after all that we still couldn't decrypt the message, error out.
    exit(mnet_server_fault(7023, 'encryption-invalid'));
}

/* Strip signature envelope (if present), try to verify any signature using our record of remote peer's public key.
 *
 * @param string $plaintextmessage XML envelope containing XMLRPC request and signature
 * @return string XMLRPC request
 */
function mnet_server_strip_signature($plaintextmessage) {
    global $MNET, $MNET_REMOTE_CLIENT;
    $sig_parser = new mnet_encxml_parser();
    $sig_parser->parse($plaintextmessage);

    if ($sig_parser->signature == '') {
        return $plaintextmessage;
    }

    // Record that the request was signed in some way
    $MNET_REMOTE_CLIENT->was_signed();

    // Load any information we have about this mnet peer
    $MNET_REMOTE_CLIENT->set_wwwroot($sig_parser->remote_wwwroot);

    $payload = base64_decode($sig_parser->data_object);
    $signature = base64_decode($sig_parser->signature);
    $certificate = $MNET_REMOTE_CLIENT->public_key;

    // If we don't have any certificate for the host, don't try to check the signature
    // Just return the parsed request
    if ($certificate == false) {
        return $payload;
    }

    // Does the signature match the data and the public cert?
    $signature_verified = openssl_verify($payload, $signature, $certificate);
    if ($signature_verified == 0) {
        // $signature was not generated for $payload using $certificate
        // Get the key the remote peer is currently publishing:
        $currkey = mnet_get_public_key($MNET_REMOTE_CLIENT->wwwroot, $MNET_REMOTE_CLIENT->application);
        // If the key the remote peer is currently publishing is different to $certificate
        if($currkey != $certificate) {
            // Try and get the server's new key through trusted means
            $MNET_REMOTE_CLIENT->refresh_key();
            // If we did manage to re-key, try to verify the signature again using the new public key.
            $certificate = $MNET_REMOTE_CLIENT->public_key;
{'fraction_non_alphanumeric': 0.13279944690902806, 'fraction_numerical': 0.006625568934723743, 'mean_word_length': 2.705016008537887, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 89, 'https://': 0, 'lorem ipsum': 0, 'www.': 16, 'xml': 18}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '476539', 'n_tokens_mistral': 5448, 'n_tokens_neox': 5157, 'n_words': 1236}