function bootstrap($wwwroot, $pubkey = null, $application) { if (substr($wwwroot, -1, 1) == '/') { $wwwroot = substr($wwwroot, 0, -1); } if (!$this->set_wwwroot($wwwroot)) { $hostname = mnet_get_hostname_from_uri($wwwroot); // Get the IP address for that host - if this fails, it will // return the hostname string $ip_address = gethostbyname($hostname); // Couldn't find the IP address? if ($ip_address === $hostname && !preg_match('/^\\d+\\.\\d+\\.\\d+.\\d+$/', $hostname)) { $this->error[] = array('code' => 2, 'text' => get_string("noaddressforhost", 'mnet')); return false; } $this->name = stripslashes($wwwroot); $this->updateparams->name = $wwwroot; // TODO: In reality, this will be prohibitively slow... need another // default - maybe blank string $homepage = file_get_contents($wwwroot); if (!empty($homepage)) { $count = preg_match("@<title>(.*)</title>@siU", $homepage, $matches); if ($count > 0) { $this->name = $matches[1]; $this->updateparams->name = addslashes($matches[1]); } } $this->wwwroot = stripslashes($wwwroot); $this->updateparams->wwwroot = $wwwroot; $this->ip_address = $ip_address; $this->updateparams->ip_address = $ip_address; $this->deleted = 0; $this->updateparams->deleted = 0; $this->application = get_record('mnet_application', 'name', $application); if (empty($this->application)) { $this->application = get_record('mnet_application', 'name', 'moodle'); } $this->applicationid = $this->application->id; $this->updateparams->applicationid = $this->application->id; if (empty($pubkey)) { $pubkeytemp = clean_param(mnet_get_public_key($this->wwwroot, $this->application), PARAM_PEM); } else { $pubkeytemp = clean_param($pubkey, PARAM_PEM); } $this->public_key_expires = $this->check_common_name($pubkeytemp); if ($this->public_key_expires == false) { return false; } $this->updateparams->public_key_expires = $this->public_key_expires; $this->updateparams->public_key = $pubkeytemp; $this->public_key = $pubkeytemp; $this->last_connect_time = 0; $this->updateparams->last_connect_time = 0; $this->last_log_id = 0; $this->updateparams->last_log_id = 0; } return true; }
function bootstrap($wwwroot, $pubkey = null, $application) { global $DB; if (substr($wwwroot, -1, 1) == '/') { $wwwroot = substr($wwwroot, 0, -1); } // If a peer record already exists for this address, // load that info and return if ($this->set_wwwroot($wwwroot)) { return true; } $hostname = mnet_get_hostname_from_uri($wwwroot); // Get the IP address for that host - if this fails, it will return the hostname string $ip_address = gethostbyname($hostname); // Couldn't find the IP address? if ($ip_address === $hostname && !preg_match('/^\\d+\\.\\d+\\.\\d+.\\d+$/', $hostname)) { throw new moodle_exception('noaddressforhost', 'mnet', '', $hostname); } $this->name = $wwwroot; // TODO: In reality, this will be prohibitively slow... need another // default - maybe blank string $homepage = download_file_content($wwwroot); if (!empty($homepage)) { $count = preg_match("@<title>(.*)</title>@siU", $homepage, $matches); if ($count > 0) { $this->name = $matches[1]; } } $this->wwwroot = $wwwroot; $this->ip_address = $ip_address; $this->deleted = 0; $this->application = $DB->get_record('mnet_application', array('name' => $application)); if (empty($this->application)) { $this->application = $DB->get_record('mnet_application', array('name' => 'moodle')); } $this->applicationid = $this->application->id; if (empty($pubkey)) { $this->public_key = clean_param(mnet_get_public_key($this->wwwroot, $this->application), PARAM_PEM); } else { $this->public_key = clean_param($pubkey, PARAM_PEM); } $this->public_key_expires = $this->check_common_name($this->public_key); $this->last_connect_time = 0; $this->last_log_id = 0; if ($this->public_key_expires == false) { $this->public_key == ''; return false; } $this->bootstrapped = true; }
exit; } else { if ($simpleform->is_submitted()) { // validation failed $noreviewform = true; } } // editing a host - load up the review form if (!empty($hostid)) { // TODO print a nice little heading $mnet_peer->set_id($hostid); echo $OUTPUT->header(); $currenttab = 'mnetdetails'; require_once $CFG->dirroot . '/admin/mnet/tabs.php'; if ($hostid != $CFG->mnet_all_hosts_id) { $mnet_peer->currentkey = mnet_get_public_key($mnet_peer->wwwroot, $mnet_peer->application); if ($mnet_peer->currentkey == $mnet_peer->public_key) { unset($mnet_peer->currentkey); } else { error_log($mnet_peer->currentkey); error_log($mnet_peer->public_key); error_log(md5($mnet_peer->currentkey)); error_log(md5($mnet_peer->public_key)); } $credentials = $mnet_peer->check_credentials($mnet_peer->public_key); $reviewform = new mnet_review_host_form(null, array('peer' => $mnet_peer)); // the second step (also the edit host form) $mnet_peer->oldpublickey = $mnet_peer->public_key; // set this so we can confirm on form post without having to recreate the mnet_peer object $reviewform->set_data((object) $mnet_peer); echo $OUTPUT->box_start();
// renew local key $mnet->replace_keys(); // send new key using key exchange transportation // make a key and exchange it with all known and active peers $mnet_peers = $DB->get_records('mnet_host', array('deleted' => 0)); if ($mnet_peers) { foreach ($mnet_peers as $peer) { if ($peer->id == $CFG->mnet_all_hosts_id || $peer->id == $CFG->mnet_localhost_id) { continue; } $application = $DB->get_record('mnet_application', array('id' => $peer->applicationid)); $mnet_peer = new mnet_peer(); $mnet_peer->set_wwwroot($peer->wwwroot); // get the sessions for each vmoodle that have same ID Number // we use a force parameter to force fetching the key remotely anyway $currentkey = mnet_get_public_key($mnet_peer->wwwroot, $application, 1); if ($currentkey) { $mnet_peer->public_key = clean_param($currentkey, PARAM_PEM); $mnet_peer->updateparams = new StdClass(); $mnet_peer->updateparams->public_key = clean_param($currentkey, PARAM_PEM); $mnet_peer->public_key_expires = $mnet_peer->check_common_name($currentkey); $mnet_peer->updateparams->public_key_expires = $mnet_peer->check_common_name($currentkey); $mnet_peer->commit(); mtrace('My key renewed at ' . $peer->wwwroot . ' till ' . userdate($mnet_peer->public_key_expires)); $trace .= userdate(time()) . ' KEY RENEW from ' . $CFG->wwwroot . ' to ' . $peer->wwwroot . " suceeded\n"; } else { mtrace('Failed renewing key with ' . $peer->wwwroot . "\n"); $trace .= userdate(time()) . ' KEY RENEW from ' . $CFG->wwwroot . ' to ' . $peer->wwwroot . " failed\n"; } } }
function mnet_server_strip_signature($plaintextmessage) { $remoteclient = get_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 $remoteclient->was_signed(); // Load any information we have about this mnet peer $remoteclient->set_wwwroot($sig_parser->remote_wwwroot); $payload = base64_decode($sig_parser->data_object); $signature = base64_decode($sig_parser->signature); $certificate = $remoteclient->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($remoteclient->wwwroot, $remoteclient->application); // If the key the remote peer is currently publishing is different to $certificate if($currkey != $certificate) { // if pushkey is already set, it means the request was encrypted to an old key // in mnet_server_strip_encryption. // if we call refresh_key() here before pushing out our new key, // and the other site ALSO has a new key, // we'll get into an infinite keyswap loop // so push just bail here, and push out the new key. // the next request will get through to refresh_key if ($remoteclient->pushkey) { return false; } // Try and get the server's new key through trusted means $remoteclient->refresh_key(); // If we did manage to re-key, try to verify the signature again using the new public key. $certificate = $remoteclient->public_key; $signature_verified = openssl_verify($payload, $signature, $certificate); } } if ($signature_verified == 1) { $remoteclient->signature_verified(); $remoteclient->touch(); } $sig_parser->free_resource(); return $payload; }
/** * Strip the encryption (XML-ENC) and signature (XML-SIG) wrappers and return the XML-RPC payload * * IF COMMUNICATION TAKES PLACE OVER UNENCRYPTED HTTP: * The payload will have been encrypted with a symmetric key. This key will * itself have been encrypted using your public key. The key is decrypted using * your private key, and then used to decrypt the XML payload. * * IF COMMUNICATION TAKES PLACE OVER UNENCRYPTED HTTP *OR* ENCRYPTED HTTPS: * In either case, there will be an XML wrapper which contains your XML-RPC doc * as an object element, a signature for that doc, and various standards- * compliant info to aid in verifying the signature. * * This function parses the encryption wrapper, decrypts the contents, parses * the signature wrapper, and if the signature matches the payload, it returns * the payload, which should be an XML-RPC request. * If there is an error, or the signatures don't match, it echoes an XML-RPC * error and exits. * * See the W3C's {@link http://www.w3.org/TR/xmlenc-core/ XML Encryption Syntax and Processing} * and {@link http://www.w3.org/TR/2001/PR-xmldsig-core-20010820/ XML-Signature Syntax and Processing} * guidelines for more detail on the XML. * * -----XML-Envelope--------------------------------- * | | * | Encrypted-Symmetric-key---------------- | * | |_____________________________________| | * | | * | Encrypted data------------------------- | * | | | | * | | -XML-Envelope------------------ | | * | | | | | | * | | | --Signature------------- | | | * | | | |______________________| | | | * | | | | | | * | | | --Signed-Payload-------- | | | * | | | | | | | | * | | | | XML-RPC Request | | | | * | | | |______________________| | | | * | | | | | | * | | |_____________________________| | | * | |_____________________________________| | * | | * |________________________________________________| * * @uses $db * @param string $HTTP_RAW_POST_DATA The XML that the client sent * @return string The XMLRPC payload. */ function mnet_server_strip_wrappers($HTTP_RAW_POST_DATA) { global $MNET, $MNET_REMOTE_CLIENT; if (isset($_SERVER)) { $crypt_parser = new mnet_encxml_parser(); $crypt_parser->parse($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)); } if ($crypt_parser->payload_encrypted) { $key = array_pop($crypt_parser->cipher); // This key is Symmetric $data = array_pop($crypt_parser->cipher); $crypt_parser->free_resource(); $payload = ''; // Initialize payload var $push_current_key = false; // True if we need to push a fresh key to the peer // &$payload $isOpen = openssl_open(base64_decode($data), $payload, base64_decode($key), $MNET->get_private_key()); if (!$isOpen) { // 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 $push_current_key = true; break; } } } if (!$isOpen) { exit(mnet_server_fault(7023, 'encryption-invalid')); } if (strpos(substr($payload, 0, 100), '<signedMessage>')) { $MNET_REMOTE_CLIENT->was_signed(); $sig_parser = new mnet_encxml_parser(); $sig_parser->parse($payload); } else { exit(mnet_server_fault(7022, 'verifysignature-error')); } } else { exit(mnet_server_fault(7024, 'payload-not-encrypted')); } unset($payload); // if the peer used one of our public keys that have expired, we will // return a signed/encrypted error message with our new public key if ($push_current_key) { // NOTE: Here, we use the 'mnet_server_fault_xml' to avoid // get_string being called on our public_key exit(mnet_server_fault_xml(7025, $MNET->public_key, $keyresource)); } /** * Get the certificate (i.e. public key) from the remote server. */ $certificate = $MNET_REMOTE_CLIENT->public_key; if ($certificate == false) { exit(mnet_server_fault(709, 'nosuchpublickey')); } $payload = base64_decode($sig_parser->data_object); // Does the signature match the data and the public cert? $signature_verified = openssl_verify($payload, base64_decode($sig_parser->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->xmlrpc_server_url); // If the key the remote peer is currently publishing is different to $certificate if ($currkey != $certificate) { // If we can't get the server's new key through trusted means, exit. if (!$MNET_REMOTE_CLIENT->refresh_key()) { exit(mnet_server_fault(7026, 'verifysignature-invalid')); } // If we did manage to re-key, try to verify the signature again against the new public key. $certificate = $MNET_REMOTE_CLIENT->public_key; $signature_verified = openssl_verify($payload, base64_decode($sig_parser->signature), $certificate); } } if ($signature_verified == 1) { $MNET_REMOTE_CLIENT->touch(); } elseif ($signature_verified == 0) { exit(mnet_server_fault(710, 'verifysignature-invalid')); } else { exit(mnet_server_fault(711, 'verifysignature-error')); } $sig_parser->free_resource(); return $payload; } else { exit(mnet_server_fault(712, "phperror")); } }
function bootstrap($wwwroot, $pubkey = null, $application, $force = false, $localname = '') { global $DB; if (substr($wwwroot, -1, 1) == '/') { $wwwroot = substr($wwwroot, 0, -1); } if (!$this->set_wwwroot($wwwroot)) { $hostname = mnet_get_hostname_from_uri($wwwroot); // Get the IP address for that host - if this fails, it will // return the hostname string $ip_address = gethostbyname($hostname); // Couldn't find the IP address? if ($ip_address === $hostname && !preg_match('/^\\d+\\.\\d+\\.\\d+.\\d+$/', $hostname)) { $this->errors[] = 'ErrCode 2 - ' . get_string("noaddressforhost", 'mnet'); return false; } if (empty($localname)) { $this->name = stripslashes($wwwroot); $this->updateparams->name = $wwwroot; } else { $this->name = $localname; $this->updateparams->name = $localname; } // TODO: In reality, this will be prohibitively slow... need another // default - maybe blank string $homepage = file_get_contents($wwwroot); if (!empty($homepage)) { $count = preg_match("@<title>(.*)</title>@siU", $homepage, $matches); if ($count > 0) { $this->name = $matches[1]; $this->updateparams->name = str_replace("'", "''", $matches[1]); } } else { // debug_trace("Missing remote real name guessing, no other side response"); } // debug_trace("final name : ".$this->name); $this->wwwroot = stripslashes($wwwroot); $this->updateparams->wwwroot = $wwwroot; $this->ip_address = $ip_address; $this->updateparams->ip_address = $ip_address; $this->deleted = 0; $this->updateparams->deleted = 0; $this->application = $DB->get_record('mnet_application', array('name' => $application)); if (empty($this->application)) { $this->application = $DB->get_record('mnet_application', array('name' => 'moodle')); } $this->applicationid = $this->application->id; $this->updateparams->applicationid = $this->application->id; // start bootstraping as usual through the system command $pubkeytemp = clean_param(mnet_get_public_key($this->wwwroot, $this->application), PARAM_PEM); if (empty($pubkey)) { // This is the key difference : force the exchange using vmoodle RPC keyswap !! if (empty($pubkeytemp)) { $pubkeytemp = clean_param(mnet_get_public_key($this->wwwroot, $this->application, $force), PARAM_PEM); } } else { $pubkeytemp = clean_param($pubkey, PARAM_PEM); } $this->public_key_expires = $this->check_common_name($pubkeytemp); if ($this->public_key_expires == false) { return false; } $this->updateparams->public_key_expires = $this->public_key_expires; $this->updateparams->public_key = $pubkeytemp; $this->public_key = $pubkeytemp; $this->last_connect_time = 0; $this->updateparams->last_connect_time = 0; $this->last_log_id = 0; $this->updateparams->last_log_id = 0; } return true; }
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; $signature_verified = openssl_verify($payload, $signature, $certificate); } } if ($signature_verified == 1) { $MNET_REMOTE_CLIENT->signature_verified(); $MNET_REMOTE_CLIENT->touch(); } $sig_parser->free_resource(); return $payload; }
} if ('input' == $form->step) { include './mnet_review.html'; } elseif ('commit' == $form->step) { $bool = $mnet_peer->commit(); if ($bool) { redirect('peers.php?step=update&hostid=' . $mnet_peer->id, get_string('changessaved')); } else { error('Invalid action parameter.', 'index.php'); } } } } elseif (is_int($hostid)) { $mnet_peer = new mnet_peer(); $mnet_peer->set_id($hostid); $currentkey = mnet_get_public_key($mnet_peer->wwwroot); if ($currentkey == $mnet_peer->public_key) { unset($currentkey); } $form = new stdClass(); if ($hostid != $CFG->mnet_all_hosts_id) { include './mnet_review.html'; } else { include './mnet_review_allhosts.html'; } } else { $hosts = get_records_select('mnet_host', " id != '{$CFG->mnet_localhost_id}' AND deleted = '0' ", 'wwwroot ASC'); if (empty($hosts)) { $hosts = array(); } include './peers.html';