コード例 #1
0
 function send($wwwroot, $use_cached_peer = true)
 {
     $this->peer = get_peer($wwwroot, $use_cached_peer);
     $this->response = '';
     $URL = $this->peer->wwwroot . $this->peer->application->xmlrpcserverurl;
     $this->requesttext = xmlrpc_encode_request($this->method, $this->params, array("encoding" => "utf-8"));
     $this->signedrequest = xmldsig_envelope($this->requesttext);
     $this->encryptedrequest = xmlenc_envelope($this->signedrequest, $this->peer->certificate);
     $config = array(CURLOPT_URL => $URL, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_USERAGENT => 'Mahara', CURLOPT_POSTFIELDS => $this->encryptedrequest, CURLOPT_HTTPHEADER => array("Content-Type: text/xml charset=UTF-8", 'Expect: '), CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => 0);
     $result = mahara_http_request($config);
     $timestamp_send = time();
     $this->rawresponse = $result->data;
     $response_code = $result->info['http_code'];
     $response_code_prefix = substr($response_code, 0, 1);
     if ('2' != $response_code_prefix) {
         if ('4' == $response_code_prefix) {
             throw new XmlrpcClientException('Client error code: ' . $response_code);
         } else {
             if ('5' == $response_code_prefix) {
                 throw new XmlrpcClientException('An error occurred at the remote server. Code: ' . $response_code);
             }
         }
     }
     $timestamp_receive = time();
     $remote_timestamp = null;
     $curl_errno = $result->errno;
     if ($curl_errno || $this->rawresponse == false) {
         throw new XmlrpcClientException('Curl error: ' . $curl_errno . ': ' . $result->error);
         return false;
     }
     try {
         $xml = new SimpleXMLElement(trim($this->rawresponse));
     } catch (Exception $e) {
         log_debug($this->rawresponse);
         throw new XmlrpcClientException('Payload is not a valid XML document (payload is above)', 6001);
     }
     try {
         if ($xml->getName() == 'encryptedMessage') {
             $payload_encrypted = true;
             $wwwroot = (string) $xml->wwwroot;
             // Strip encryption, using an older code is OK, because we're the client.
             // The server is able to respond with the correct key, be we're not
             $payload = xmlenc_envelope_strip($xml, true);
         }
         if ($xml->getName() == 'signedMessage') {
             $payload_signed = true;
             $remote_timestamp = $xml->timestamp;
             $payload = xmldsig_envelope_strip($xml);
         }
     } catch (CryptException $e) {
         throw new XmlrpcClientException("An error occurred while decrypting a message sent by {$wwwroot}. Unable to authenticate the user.");
     }
     if ($xml->getName() == 'methodResponse') {
         $this->response = xmlrpc_decode($payload);
         // Margin of error is the time it took the request to complete.
         $margin_of_error = $timestamp_receive - $timestamp_send;
         // Guess the time gap between sending the request and the remote machine
         // executing the time() function. Marginally better than nothing.
         $hysteresis = $margin_of_error / 2;
         if (!empty($remote_timestamp)) {
             $remote_timestamp = $remote_timestamp - $hysteresis;
             $time_offset = $remote_timestamp - $timestamp_send;
             if ($time_offset > self::get_max_server_time_difference()) {
                 throw new XmlrpcClientException('Time drift (' . $margin_of_error . ', ' . $time_offset . ') is too large.');
             }
         }
         if (is_array($this->response) && array_key_exists('faultCode', $this->response)) {
             if ($this->response['faultCode'] == 7025) {
                 log_info('Remote application has sent us a new public key');
                 // The remote application sent back a new public key, the
                 // old one must have expired
                 if (array_key_exists('faultString', $this->response)) {
                     $details = openssl_x509_parse($this->response['faultString']);
                     if (isset($details['validTo_time_t'])) {
                         $updateobj = (object) array('publickey' => $this->response['faultString'], 'publickeyexpires' => $details['validTo_time_t']);
                         $whereobj = (object) array('wwwroot' => $wwwroot);
                         update_record('host', $updateobj, $whereobj);
                         log_info('New key has been imported. Valid until ' . date('Y/m/d h:i:s', $details['validTo_time_t']));
                         // Send request again. But don't use the cached
                         // peer, look it up again now we've changed the
                         // public key
                         $this->send($wwwroot, false);
                     } else {
                         throw new XmlrpcClientException('Could not parse new public key');
                     }
                 } else {
                     throw new XmlrpcClientException('Remote site claims to have sent a public key, but they LIE');
                 }
             }
             throw new XmlrpcClientException('Unknown error occurred: ' . $this->response['faultCode'] . ': ' . $this->response['faultString']);
         }
         // Clean up so object can be re-used.
         $this->requesttext = '';
         $this->signedrequest = '';
         $this->encryptedrequest = '';
         $this->params = array();
         $this->method = '';
         return true;
     } else {
         throw new XmlrpcClientException('Unrecognized XML document form: ' . $payload);
     }
 }
コード例 #2
0
ファイル: locallib.php プロジェクト: rboyatt/mahara
 /**
  * Chance for each protocol to modify the out going
  * raw payload - eg: SOAP encryption and signatures
  *
  * @param string $response The raw response value
  *
  * @return content
  */
 protected function modify_result($response)
 {
     if (!empty($this->publickey)) {
         // do sigs + encrypt
         require_once get_config('docroot') . 'api/xmlrpc/lib.php';
         $openssl = OpenSslRepo::singleton();
         if ($this->payload_signed) {
             // Sign and encrypt our response, even though we don't know if the
             // request was signed and encrypted
             $response = xmldsig_envelope($response);
         }
         if ($this->payload_encrypted) {
             $response = xmlenc_envelope($response, $this->publickey);
         }
     }
     return $response;
 }
コード例 #3
0
ファイル: server.php プロジェクト: Br3nda/mahara
        xmlrpc_error($e->getMessage(), $e->getCode());
        $response = ob_get_contents();
        ob_end_clean();
        // Sign and encrypt our response, even though we don't know if the
        // request was signed and encrypted
        $response = xmldsig_envelope($response);
        $peer = get_peer($REMOTEWWWROOT);
        $response = xmlenc_envelope($response, $peer->certificate);
        echo $response;
        exit;
    }
}
if ($xml->getName() == 'methodCall') {
    // $payload ?
    if (empty($xml->methodName)) {
        throw new XmlrpcServerException('Payload is not an XML-RPC document', 6008);
    }
    $Dispatcher = new Dispatcher($payload, $payload_signed, $payload_encrypted);
    if ($payload_signed) {
        $response = xmldsig_envelope($Dispatcher->response);
    } else {
        $response = $Dispatcher->response;
    }
    if ($payload_encrypted) {
        $peer = get_peer($REMOTEWWWROOT);
        $response = xmlenc_envelope($response, $peer->certificate);
    }
    echo $response;
} else {
    throw new XmlrpcServerException('Unrecognized XML document form: ' . var_export($xml, 1), 6009);
}