function xmlrpc_request($host, $port, $location, $function, &$request_data) { /* * This method sends a very basic XML-RPC request. $host, $port, $location, * and $function are pretty simple. $request_data can be any PHP type, * and this function returns the PHP type of whatever the xmlrpc function * returns. * * WARNING: This function dies upon failure. */ // Send request $request_xml = xmlrpc_encode_request($function, $request_data); // Split out response into headers, and xml $response = urlpost($host, $port, $location, $request_xml); $response_array = split("\r\n\r\n", $response, 2); $response_headers = split("\r\n", $response_array[0]); $response_xml = $response_array[1]; $http_array = split(" ", $response_headers[0], 3); if ($http_array[1] != "200") { trigger_error("xmlrpc request failed: ({$http_array[1]}, {$http_array[2]}) at {$host}:{$port} using {$location}"); } else { // Get native PHP types and return them for data. $response_data = xmlrpc_decode_request($response_xml, $function); return $response_data; } }
public function registerObjects() { $postRequest = $this->getRequest(); //Utils::debug($postRequest, 'rpc.log', false); //extract method $methodRequest = ''; $classname = ''; $method = ''; $result = xmlrpc_decode_request($postRequest, $methodRequest); if ($methodRequest) { list($classname, $method) = explode('.', $methodRequest); } //Utils::debug("class = $classname, method = $method"); try { $this->director->pluginManager->loadPlugin($classname); } catch (Exception $e) { // normal plugin failed, try to load admin plugin try { $this->director->adminManager->loadPlugin($classname); } catch (Exception $err) { $this->log->error("error loading coreplugin : {$err}"); } //throw new Exception($e->getMessage()); } }
public function __call($method, $params) { if (!function_exists('xmlrpc_encode_request')) { throw new \Exception("The php5-xmlrpc extension is not installed. Please install this to use this functionality"); } $xml = xmlrpc_encode_request($method, $params); //\GO::debug($xml); if ($this->curl_hdl === null) { // Create cURL resource $this->curl_hdl = curl_init(); // Configure options curl_setopt($this->curl_hdl, CURLOPT_URL, $this->uri); curl_setopt($this->curl_hdl, CURLOPT_HEADER, 0); curl_setopt($this->curl_hdl, CURLOPT_RETURNTRANSFER, true); curl_setopt($this->curl_hdl, CURLOPT_POST, true); curl_setopt($this->curl_hdl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($this->curl_hdl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($this->curl_hdl, CURLOPT_TIMEOUT, 10); if (isset($this->_user)) { curl_setopt($this->curl_hdl, CURLOPT_USERPWD, $this->_user . ":" . $this->_pass); } } curl_setopt($this->curl_hdl, CURLOPT_POSTFIELDS, $xml); // Invoke RPC command $response = curl_exec($this->curl_hdl); $errorNo = curl_errno($this->curl_hdl); if ($errorNo) { throw new \Exception($this->_curlErrorCodes[$errorNo]); } //\GO::debug($response); $result = xmlrpc_decode_request($response, $method); return $result; }
/** * This method parses the request input, it needs to get: * 1/ user authentication - username+password or token * 2/ function name * 3/ function parameters */ protected function parse_request() { // Retrieve and clean the POST/GET parameters from the parameters specific to the server. parent::set_web_service_call_settings(); // Get GET and POST parameters. $methodvariables = array_merge($_GET, $_POST); if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) { $this->username = isset($methodvariables['wsusername']) ? $methodvariables['wsusername'] : null; unset($methodvariables['wsusername']); $this->password = isset($methodvariables['wspassword']) ? $methodvariables['wspassword'] : null; unset($methodvariables['wspassword']); } else { $this->token = isset($methodvariables['wstoken']) ? $methodvariables['wstoken'] : null; unset($methodvariables['wstoken']); } // Get the XML-RPC request data. $rawpostdata = file_get_contents("php://input"); $methodname = null; // Decode the request to get the decoded parameters and the name of the method to be called. $decodedparams = xmlrpc_decode_request($rawpostdata, $methodname); $methodinfo = external_api::external_function_info($methodname); $methodparams = array_keys($methodinfo->parameters_desc->keys); // Add the decoded parameters to the methodvariables array. if (is_array($decodedparams)) { foreach ($decodedparams as $index => $param) { // See MDL-53962 - XML-RPC requests will usually be sent as an array (as in, one with indicies). // We need to use a bit of "magic" to add the correct index back. Zend used to do this for us. $methodvariables[$methodparams[$index]] = $param; } } $this->functionname = $methodname; $this->parameters = $methodvariables; }
/** * This method parses the request input, it needs to get: * 1/ user authentication - username+password or token * 2/ function name * 3/ function parameters */ protected function parse_request() { // Retrieve and clean the POST/GET parameters from the parameters specific to the server. parent::set_web_service_call_settings(); // Get GET and POST parameters. $methodvariables = array_merge($_GET, $_POST); if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) { $this->username = isset($methodvariables['wsusername']) ? $methodvariables['wsusername'] : null; unset($methodvariables['wsusername']); $this->password = isset($methodvariables['wspassword']) ? $methodvariables['wspassword'] : null; unset($methodvariables['wspassword']); } else { $this->token = isset($methodvariables['wstoken']) ? $methodvariables['wstoken'] : null; unset($methodvariables['wstoken']); } // Get the XML-RPC request data. $rawpostdata = file_get_contents("php://input"); $methodname = null; // Decode the request to get the decoded parameters and the name of the method to be called. $decodedparams = xmlrpc_decode_request($rawpostdata, $methodname); // Add the decoded parameters to the methodvariables array. if (is_array($decodedparams)) { foreach ($decodedparams as $param) { // Check if decoded param is an associative array. if (is_array($param) && array_keys($param) !== range(0, count($param) - 1)) { $methodvariables = array_merge($methodvariables, $param); } else { $methodvariables[] = $param; } } } $this->functionname = $methodname; $this->parameters = $methodvariables; }
function __construct($payload, $payload_signed, $payload_encrypted) { $this->payload = $payload; // xmlrpc_decode_request is defined such that the '$method' string is // passed in by reference. $this->params = xmlrpc_decode_request($this->payload, $this->method, 'UTF-8'); // The method name is not allowed to have a dot, except for a single dot // which preceeds the php extension. It can have slashes but it cannot // begin with a slash. We specifically don't want .. to be possible. if (0 == preg_match("@^[A-Za-z0-9]+/[A-Za-z0-9/_-]+(\\.php/)?[A-Za-z0-9_-]+\$@", $this->method)) { throw new XmlrpcServerException('The function does not exist', 6010); } if ($payload_signed && $payload_encrypted || $this->method == 'system/keyswap') { // The remote server's credentials checked out. // You might want to enable some methods for unsigned/unencrypted // transport } else { // For now, we throw an exception throw new XmlrpcServerException('The signature on your message was not valid', 6005); } // The system methods are treated differently. if (array_key_exists($this->method, $this->system_methods)) { $xmlrpcserver = xmlrpc_server_create(); xmlrpc_server_register_method($xmlrpcserver, $this->method, array(&$this, $this->system_methods[$this->method])); } else { // Security: I'm thinking that we should not return separate errors for // the file not existing, the file not being readable, etc. as // it might provide an opportunity for outsiders to scan the // server for random files. So just a single message/code for // all failures here kthxbye. if (strpos($this->method, '/') !== false) { $this->callstack = explode('/', $this->method); } else { throw new XmlrpcServerException('The function does not exist', 6011); } // Read custom xmlrpc functions from local if (function_exists('local_xmlrpc_services')) { foreach (local_xmlrpc_services() as $name => $localservices) { $this->services[$name] = array_merge($this->services[$name], $localservices); } } foreach ($this->services as $container) { if (array_key_exists($this->method, $container)) { $xmlrpcserver = xmlrpc_server_create(); $bool = xmlrpc_server_register_method($xmlrpcserver, $this->method, 'api_dummy_method'); $this->response = xmlrpc_server_call_method($xmlrpcserver, $payload, $container[$this->method], array("encoding" => "utf-8")); $bool = xmlrpc_server_destroy($xmlrpcserver); return $this->response; } } throw new XmlrpcServerException('No such method: ' . $this->method); } $temp = ''; $this->response = xmlrpc_server_call_method($xmlrpcserver, $payload, $temp, array("encoding" => "utf-8")); return $this->response; }
/** * Reads the HTTP request from client and decodes the XML data * * @return void */ public function readRequest() { $this->_debug("-----> " . __CLASS__ . '::' . __FUNCTION__ . "()", 9); // Parent will do the request reading parent::readRequest(); // Assign and decode the request $this->requestRawXml =& $this->requestRawBody; $this->params = xmlrpc_decode_request($this->requestRawXml, $this->method); // Set the response header $this->setResponseHeader('Content-type', 'text/xml'); }
function decodeStream($rawResponse) { /// @todo test if this automatically groks encoding from xml or not... $meth = ''; $resp = xmlrpc_decode_request($rawResponse, $meth); if (!is_array($resp)) { return false; } $this->Name = $meth; $this->Parameters = $resp; return true; }
/** * Handle RPC request(s). * Fluent interface. * * @param boolean|string $request RPC request (string), FALSE read from php://input once or TRUE to keep listing on php://input for multiple requests * @return RPC_Server_XMLRPC * * @todo implement keep alive */ public function handle($request = false) { $keep_alive = (int) $request === 1; if ($keep_alive || empty($request)) { $request = ""; while ($line = fread(STDIN, 1024)) { $request .= $line; if (substr($request, -1) == "") { break; } } $request = substr($request, 0, strlen($request) - 1); } try { $method = null; $args = xmlrpc_decode_request($request, $method); if (empty($method)) { throw new Exception("Invalid XMLRPC request."); } if (!is_callable(array($this->object, $method))) { throw new Exception("RPC call failed: Unable to call method '{$method}'."); } $result = call_user_func_array(array($this->object, $method), $args); $output = xmlrpc_encode_request(null, $result); } catch (ExpectedException $e) { $output = xmlrpc_encode(array("faultCode" => $e->getCode(), "faultString" => $e->getMessage())); } catch (\Exception $e) { $output = xmlrpc_encode(array("faultCode" => -1, "faultString" => "Unexpected exception.")); $this->putExtraInfo('X-Exception', $e->getMessage()); if (class_exists(__NAMESPACE__ . '::ErrorHandler', false) && ErrorHandler::isInit()) { ErrorHandler::i()->handleException($e); } } $content_type = HTTP::header_getValue('Content-Type'); if (empty($content_type) || $content_type == 'text/xml') { fwrite($this->stream, $output); } else { if (HTTP::headers_sendable()) { if ($keep_alive) { trigger_error("Using keep-alive together with sending non-XMLRPC is not allowed. Found header 'Content-Type: {$content_type}'.", E_USER_WARNING); fwrite($this->stream, xmlrpc_encode(array("faultCode" => 0, "faultString" => "Could not send non-XMLRPC output because of keep-alive."))); } } else { $this->putExtraInfo('Content-Type', $content_type); } } return $this; }
public function findRoute($path) { global $HTTP_RAW_POST_DATA; $result = parent::findRoute($path); //$rawdata = xmlrpc_encode_request("authorize", array( "cons", "cons" )); //if ((!$result["action"] || !$result["params"]) && ($rawdata)) if ((!$result["action"] || !$result["params"]) && ($rawdata = $HTTP_RAW_POST_DATA)) { $params = xmlrpc_decode_request($rawdata, &$action); if (!$result["action"]) { $result["action"] = $action; } if (!$result["params"]) { $result["params"] = $params; } } return $result; }
public function fromXmlString($xmlString) { $this->parameters = xmlrpc_decode_request($xmlString, $this->methodName); $this->fixupParameter($this->parameters); if ($this->methodName === null) { throw new UnexpectedValueException("Invalid XML-RPC structure (/methodCall/methodName not found)"); } if ($this->parameters === null) { if (($simpleXml = @simplexml_load_string($xmlString)) === false) { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = $error->message; } throw new UnexpectedValueException("Invalid XML-RPC message:" . implode("\n", $errors)); } } }
/** * This is the main handle for the xmlrpc calls */ public function executeRPC2($request) { // get all the defined RPC $rpc_functions = $this->getRPCFunctions(); // http POST method is required for modifying the database $this->forward404Unless($request->isMethod('post'), "HTTP POST is required"); // log to debug ezDbg::err("enter xmlrpc"); // get xmlrpc request string posted as a raw $xmlrpc_reqstr = file_get_contents("php://input"); // parse the xmlrpc_reqstr $method_name = null; $xmlrpc_params = xmlrpc_decode_request($xmlrpc_reqstr, &$method_name); ezDbg::err("enter method_name={$method_name} xmlrpc param=" . print_r($xmlrpc_params, true)); if (!isset($rpc_functions[$method_name])) { $xmlrpc_resp = array("faultCode" => 1, "faultString" => "unknown method name (" . $method_name . ")"); } else { $rpc_function = $rpc_functions[$method_name]; $nparam = $rpc_function['nparam']; if (count($xmlrpc_params) < $nparam) { $xmlrpc_resp = array("faultCode" => 1, "faultString" => $method_name . " require " . $nparam . " parameters."); } else { try { ezDbg::err('trying to call (' . $rpc_function['function'] . ')', $xmlrpc_params); $xmlrpc_resp = call_user_func_array($rpc_function['function'], $xmlrpc_params); //$xmlrpc_resp = sfWebRPCPluginDemo::superAddFct(2,3); } catch (Exception $e) { $xmlrpc_resp = array("faultCode" => 1, "faultString" => "" . $e->getMessage()); } } } // encode the xmlrpc_resp $xmlrpc_respstr = xmlrpc_encode($xmlrpc_resp); // KLUDGE: xmlrpc_encode is unable to add the methodResponse required $arr = split("\n", $xmlrpc_respstr); $arr[0] .= "\n<methodResponse>"; $arr[count($arr) - 1] = "</methodResponse>"; $xmlrpc_respstr = implode("\n", $arr); ezDbg::err("enter xmlrpc resp=" . print_r($xmlrpc_respstr, true)); // disable the web_debug bar sfConfig::set('sf_web_debug', false); // return the $value in xml $this->getResponse()->setHttpHeader('Content-Type', 'text/xml'); return $this->renderText($xmlrpc_respstr); }
/** * Parse request * * @param \Zend\Http\Request $request * @param \Zend\Http\Response $request * @return string|null $error */ public function parse(Request $request, Response $response) { $error = parent::parse($request, $response); if ($error) { return $error; } $method = null; $params = xmlrpc_decode_request($request->getContent(), $method, 'utf-8'); if (!$params) { return self::PARSE; } if (empty($method) || empty($params)) { return self::INVALID_REQUEST; } $this->method = $method; $this->params = $params; return null; }
public function inputFilter($data, stdClass $context) { if ($data !== "" && $data[0] === '<') { $context->userdata->format = "xmlrpc"; $method = null; $params = xmlrpc_decode_request($data, $method, "UTF-8"); $stream = new BytesIO(); $writer = new Writer($stream, true); if (isset($method)) { $stream->write(Tags::TagCall); $writer->writeString($method); if (isset($params)) { $writer->writeArray($params); } } $stream->write(Tags::TagEnd); $data = $stream->toString(); } return $data; }
/** * @param Request $request * @return XmlRpcRequest * @throws RpcException */ public function createRequest(Request $request) { if (!$request->isMethod('POST')) { throw new InvalidRequestException(self::MESSAGE_INVALID_HTTP_METHOD); } if ($request->getContentType() != 'xml') { throw new InvalidRequestException(self::MESSAGE_INVALID_CONTENT_TYPE); } $params = xmlrpc_decode_request($request->getContent(), $method, 'UTF-8'); if (is_null($method)) { throw new RequestParseException(self::MESSAGE_INVALID_BODY); } if (empty($method)) { throw new InvalidRequestException(self::MESSAGE_METHOD_REQUIRED); } if (!is_array($params)) { throw new InvalidRequestException(self::MESSAGE_METHOD_PARAMS_TYPE); } return new XmlRpcRequest($request, $method, $params); }
public function index() { $request_xml = file_get_contents("php://input"); $method = null; $params = xmlrpc_decode_request($request_xml, &$method); if (strpos($method, '.')) { $action = explode('.', $method); if (file_exists(BASE_DIR . 'controllers/' . $action[0] . '.php')) { include $action[0] . '.php'; $classname = ucwords($action[0] . 'Controller'); $obj = new $classname(); if (method_exists($obj, $action[1])) { $results = $obj->{$action[1]}($params[0]); header("Content-type:text/xml"); echo xmlrpc_encode_request(NULL, $results); exit; } } } }
/** * handle incoming XML RPC requests * * @return null */ public function handle() { try { // Get the XMLRPC request (raw POST data) $rawHTTPContents = file_get_contents("php://input"); // some debugging // file_put_contents("xmlrpc_messages.txt", // "Request at XML-RPC server = " . $rawHTTPContents ."\n", // FILE_APPEND); // decode xmlrpc request $params = xmlrpc_decode_request($rawHTTPContents, $method); SCA::$logger->log("Request {$rawHTTPContents}"); SCA::$logger->log("handle request {$method}"); if ($method == null || strlen($method) == 0) { $error["faultCode"] = 32600; $error["faultString"] = "Invalid XML-RPC request : {$rawHTTPContents}"; $response = xmlrpc_encode_request(null, $error); } else { if (strpos($method, "system.") === 0) { $response = $this->service_wrapper->callSystemMethod($rawHTTPContents); // some debugging // file_put_contents("xmlrpc_messages.txt", // "Response at XML-RPC server = " . $response . "\n", // FILE_APPEND); } else { $response = $this->service_wrapper->__call($method, $params); } } } catch (Exception $ex) { $error["faultCode"] = $ex instanceof SCA_RuntimeException ? 32000 : 32500; $error["faultString"] = $ex->__toString(); $response = xmlrpc_encode_request(null, $error); } // some debugging // file_put_contents("xmlrpc_messages.txt", // "Response at XML-RPC server = " . $response . "\n", // FILE_APPEND); header('Content-type: text/xml'); echo $response; return; }
/** * Initialize this Request. * * @param AgaviContext An AgaviContext instance. * @param array An associative array of initialization parameters. * * @throws <b>AgaviInitializationException</b> If an error occurs while * initializing this Request. * * @author David Zülke <*****@*****.**> * @since 0.11.0 */ public function initialize(AgaviContext $context, array $parameters = array()) { parent::initialize($context, $parameters); $decoded = (array) xmlrpc_decode_request($this->input, $this->invokedMethod, isset($parameters['encoding']) ? $parameters['encoding'] : 'utf-8'); $akeys = array_keys($decoded); if (count($decoded) == 1 && is_int($key = array_pop($akeys)) && is_array($decoded[$key])) { $decoded = $decoded[$key]; } $rdhc = $this->getParameter('request_data_holder_class'); $rd = new $rdhc(array(constant("{$rdhc}::SOURCE_PARAMETERS") => (array) $decoded)); if ($this->getParameter('use_module_action_parameters')) { $split = explode(':', $this->invokedMethod); if (count($split) == 2) { $rd->setParameter($this->getParameter('module_accessor'), $split[0]); $rd->setParameter($this->getParameter('action_accessor'), $split[1]); } else { $rd->setParameter($this->getParameter('action_accessor'), $this->invokedMethod); } } $this->setRequestData($rd); }
/** * If security checks are passed, dispatch the request to the function/method * * The config variable 'mnet_dispatcher_mode' can be: * strict: Only execute functions that are in specific files * off: The default - don't execute anything * * @param string $payload The XML-RPC request * * @throws mnet_server_exception * * @return No return val - just echo the response */ function mnet_server_dispatch($payload) { global $CFG, $DB; $remoteclient = get_mnet_remote_client(); // xmlrpc_decode_request returns an array of parameters, and the $method // variable (which is passed by reference) is instantiated with the value from // the methodName tag in the xml payload // xmlrpc_decode_request($xml, &$method) $params = xmlrpc_decode_request($payload, $method); // $method is something like: "mod/forum/lib.php/forum_add_instance" // $params is an array of parameters. A parameter might itself be an array. // Whitelist characters that are permitted in a method name // The method name must not begin with a / - avoid absolute paths // A dot character . is only allowed in the filename, i.e. something.php if (0 == preg_match("@^[A-Za-z0-9]+/[A-Za-z0-9/_\.-]+(\.php/)?[A-Za-z0-9_-]+$@",$method)) { throw new mnet_server_exception(713, 'nosuchfunction'); } if(preg_match("/^system\./", $method)) { $callstack = explode('.', $method); } else { $callstack = explode('/', $method); // callstack will look like array('mod', 'forum', 'lib.php', 'forum_add_instance'); } /** * What has the site administrator chosen as his dispatcher setting? * strict: Only execute functions that are in specific files * off: The default - don't execute anything */ ////////////////////////////////////// OFF if (!isset($CFG->mnet_dispatcher_mode) ) { set_config('mnet_dispatcher_mode', 'off'); throw new mnet_server_exception(704, 'nosuchservice'); } elseif ('off' == $CFG->mnet_dispatcher_mode) { throw new mnet_server_exception(704, 'nosuchservice'); ////////////////////////////////////// SYSTEM METHODS } elseif ($callstack[0] == 'system') { $functionname = $callstack[1]; $xmlrpcserver = xmlrpc_server_create(); // register all the system methods $systemmethods = array('listMethods', 'methodSignature', 'methodHelp', 'listServices', 'listFiles', 'retrieveFile', 'keyswap'); foreach ($systemmethods as $m) { // I'm adding the canonical xmlrpc references here, however we've // already forbidden that the period (.) should be allowed in the call // stack, so if someone tries to access our XMLRPC in the normal way, // they'll already have received a RPC server fault message. // Maybe we should allow an easement so that regular XMLRPC clients can // call our system methods, and find out what we have to offer? $handler = 'mnet_system'; if ($m == 'keyswap') { $handler = 'mnet_keyswap'; } if ($method == 'system.' . $m || $method == 'system/' . $m) { xmlrpc_server_register_method($xmlrpcserver, $method, $handler); $response = xmlrpc_server_call_method($xmlrpcserver, $payload, $remoteclient, array("encoding" => "utf-8")); $response = mnet_server_prepare_response($response); echo $response; xmlrpc_server_destroy($xmlrpcserver); return; } } throw new mnet_server_exception(7018, 'nosuchfunction'); //////////////////////////////////// NORMAL PLUGIN DISPATCHER } else { // anything else comes from some sort of plugin if ($rpcrecord = $DB->get_record('mnet_rpc', array('xmlrpcpath' => $method))) { $response = mnet_server_invoke_plugin_method($method, $callstack, $rpcrecord, $payload); $response = mnet_server_prepare_response($response); echo $response; return; // if the rpc record isn't found, check to see if dangerous mode is on ////////////////////////////////////// DANGEROUS } else if ('dangerous' == $CFG->mnet_dispatcher_mode && $remoteclient->plaintext_is_ok()) { $functionname = array_pop($callstack); $filename = clean_param(implode('/',$callstack), PARAM_PATH); if (0 == preg_match("/php$/", $filename)) { // Filename doesn't end in 'php'; possible attack? // Generate error response - unable to locate function throw new mnet_server_exception(7012, 'nosuchfunction'); } // The call stack holds the path to any include file $includefile = $CFG->dirroot.'/'.$filename; $response = mnet_server_invoke_dangerous_method($includefile, $functionname, $method, $payload); echo $response; return; } } throw new mnet_server_exception(7012, 'nosuchfunction'); }
/** * Call a method on the server. The result is returned decoded as * native PHP data. * * @param string $method The method to call * @param any $data The data * @return any The result data */ function call($method, $args = null) { logger::debug("Sending XmlrpcRequest to %s ...", $method); $req = xmlrpc_encode_request($method, $args); logger::debug('%s', $req); $opts = array('method' => 'post', 'parameters' => $req, 'content-type' => 'text/xml'); if ($this->username) { $opts['username'] = $this->username; $opts['password'] = $this->password; } $opts = array_merge($opts, $this->httpopts); $ret = new HttpRequest($this->url, $opts); logger::debug('Response: %s', $ret->responseText()); $mtd = null; $dec = xmlrpc_decode_request($ret->responseText(), $mtd); /* if ($dec && arr::hasKey($dec,'faultCode')) { printf("Fault\n"); } */ return $dec; /* // Encode the request $xml = xmlrpc_encode_request( $method, $args ); // Send it to the server $sparams = array('http' => array( 'method' => 'POST', 'content' => $xml, 'header' => array( 'content-type' => 'text/xml' ) )); $ctx = stream_context_create($params); $fp = @fopen($this->url, 'rb', false, $ctx); if (!$fp) { throw new Exception("Problem with $this->url, $php_errormsg"); } $response = @stream_get_contents($fp); if ($response === false) { throw new Exception("Problem reading data from $url, $php_errormsg"); } // Parse the output $ret = xmlrpc_decode_request($response,$mtd); return $ret; */ }
/** * If security checks are passed, dispatch the request to the function/method * * The config variable 'mnet_dispatcher_mode' can be: * strict: Only execute functions that are in specific files * off: The default - don't execute anything * * @param string $payload The XML-RPC request * @return No return val - just echo the response */ function mnet_server_dispatch($payload) { global $CFG, $MNET_REMOTE_CLIENT; // xmlrpc_decode_request returns an array of parameters, and the $method // variable (which is passed by reference) is instantiated with the value from // the methodName tag in the xml payload // xmlrpc_decode_request($xml, &$method) $params = xmlrpc_decode_request($payload, $method); // $method is something like: "mod/forum/lib.php/forum_add_instance" // $params is an array of parameters. A parameter might itself be an array. // Whitelist characters that are permitted in a method name // The method name must not begin with a / - avoid absolute paths // A dot character . is only allowed in the filename, i.e. something.php if (0 == preg_match("@^[A-Za-z0-9]+/[A-Za-z0-9/_-]+(\\.php/)?[A-Za-z0-9_-]+\$@", $method)) { exit(mnet_server_fault(713, 'nosuchfunction')); } if (preg_match("/^system\\./", $method)) { $callstack = explode('.', $method); } else { $callstack = explode('/', $method); // callstack will look like array('mod', 'forum', 'lib.php', 'forum_add_instance'); } /** * What has the site administrator chosen as his dispatcher setting? * strict: Only execute functions that are in specific files * off: The default - don't execute anything */ ////////////////////////////////////// OFF if (!isset($CFG->mnet_dispatcher_mode)) { set_config('mnet_dispatcher_mode', 'off'); exit(mnet_server_fault(704, 'nosuchservice')); } elseif ('off' == $CFG->mnet_dispatcher_mode) { exit(mnet_server_fault(704, 'nosuchservice')); ////////////////////////////////////// SYSTEM METHODS } elseif ($callstack[0] == 'system') { $functionname = $callstack[1]; $xmlrpcserver = xmlrpc_server_create(); // I'm adding the canonical xmlrpc references here, however we've // already forbidden that the period (.) should be allowed in the call // stack, so if someone tries to access our XMLRPC in the normal way, // they'll already have received a RPC server fault message. // Maybe we should allow an easement so that regular XMLRPC clients can // call our system methods, and find out what we have to offer? xmlrpc_server_register_method($xmlrpcserver, 'system.listMethods', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system/listMethods', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system.methodSignature', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system/methodSignature', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system.methodHelp', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system/methodHelp', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system.listServices', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system/listServices', 'mnet_system'); xmlrpc_server_register_method($xmlrpcserver, 'system.keyswap', 'mnet_keyswap'); xmlrpc_server_register_method($xmlrpcserver, 'system/keyswap', 'mnet_keyswap'); if ($method == 'system.listMethods' || $method == 'system/listMethods' || $method == 'system.methodSignature' || $method == 'system/methodSignature' || $method == 'system.methodHelp' || $method == 'system/methodHelp' || $method == 'system.listServices' || $method == 'system/listServices' || $method == 'system.keyswap' || $method == 'system/keyswap') { $response = xmlrpc_server_call_method($xmlrpcserver, $payload, $MNET_REMOTE_CLIENT, array("encoding" => "utf-8")); $response = mnet_server_prepare_response($response); } else { exit(mnet_server_fault(7018, 'nosuchfunction')); } xmlrpc_server_destroy($xmlrpcserver); echo $response; ////////////////////////////////////// STRICT AUTH } elseif ($callstack[0] == 'auth') { // Break out the callstack into its elements list($base, $plugin, $filename, $methodname) = $callstack; // We refuse to include anything that is not auth.php if ($filename == 'auth.php' && is_enabled_auth($plugin)) { $authclass = 'auth_plugin_' . $plugin; $includefile = '/auth/' . $plugin . '/auth.php'; $response = mnet_server_invoke_method($includefile, $methodname, $method, $payload, $authclass); $response = mnet_server_prepare_response($response); echo $response; } else { // Generate error response - unable to locate function exit(mnet_server_fault(702, 'nosuchfunction')); } ////////////////////////////////////// STRICT ENROL } elseif ($callstack[0] == 'enrol') { // Break out the callstack into its elements list($base, $plugin, $filename, $methodname) = $callstack; if ($filename == 'enrol.php' && is_enabled_enrol($plugin)) { $enrolclass = 'enrolment_plugin_' . $plugin; $includefile = '/enrol/' . $plugin . '/enrol.php'; $response = mnet_server_invoke_method($includefile, $methodname, $method, $payload, $enrolclass); $response = mnet_server_prepare_response($response); echo $response; } else { // Generate error response - unable to locate function exit(mnet_server_fault(703, 'nosuchfunction')); } ////////////////////////////////////// STRICT MOD/* } elseif ($callstack[0] == 'mod' || 'dangerous' == $CFG->mnet_dispatcher_mode) { list($base, $module, $filename, $functionname) = $callstack; ////////////////////////////////////// STRICT MOD/* if ($base == 'mod' && $filename == 'rpclib.php') { $includefile = '/mod/' . $module . '/rpclib.php'; $response = mnet_server_invoke_method($includefile, $functionname, $method, $payload); $response = mnet_server_prepare_response($response); echo $response; ////////////////////////////////////// DANGEROUS } elseif ('dangerous' == $CFG->mnet_dispatcher_mode && $MNET_REMOTE_CLIENT->plaintext_is_ok()) { $functionname = array_pop($callstack); if ($MNET_REMOTE_CLIENT->plaintext_is_ok()) { $filename = clean_param(implode('/', $callstack), PARAM_PATH); if (0 == preg_match("/php\$/", $filename)) { // Filename doesn't end in 'php'; possible attack? // Generate error response - unable to locate function exit(mnet_server_fault(7012, 'nosuchfunction')); } // The call stack holds the path to any include file $includefile = $CFG->dirroot . '/' . $filename; $response = mnet_server_invoke_method($includefile, $functionname, $method, $payload); echo $response; } } else { // Generate error response - unable to locate function exit(mnet_server_fault(7012, 'nosuchfunction')); } } else { // Generate error response - unable to locate function exit(mnet_server_fault(7012, 'nosuchfunction')); } }
function xmlrpc_server() { global $xmlrpc_methods; #-- server is active define("XMLRPC_SERVER", getmypid()); if (XMLRPC_DEBUG) { error_reporting(E_ALL ^ E_NOTICE); } ob_start(); #-- standard reply headers header("Accept: " . XMLRPC_MIME_NEW . ", " . XMLRPC_MIME_OLD . "; q=0.5"); header("Accept-Encoding: deflate"); header("X-Server: " . XMLRPC_UA); header("Connection: close"); header("Cache-Control: private"); #-- fixes for PHP/Apache if (function_exists("getallheaders")) { foreach (getallheaders() as $i => $v) { $_SERVER[strtoupper(strtr("HTTP_{$i}", "-", "_"))] = $v; } } #-- check and get call $allowed = array("REQUEST_METHOD" => array("POST", "PUT", "CALL"), "CONTENT_TYPE" => array(XMLRPC_MIME_NEW, XMLRPC_MIME_OLD)); foreach ($allowed as $WHAT => $WHICH) { if (!in_array(trim(strtok($WRONG = $_SERVER[$WHAT], ";,(")), $WHICH)) { header("Status: 400 Go Away, Stupid!"); if (!$WRONG) { $WRONG = "undefined"; } die("<h2>Error</h2>Your request was bogus, <b>{$WHAT}</b> must be <i>" . implode("</i> or <i>", $WHICH) . "</i>, but yours was '<tt>{$WRONG}</tt>'.\n"); } } if (!($xml_request = xmlrpc_fetch_post_chunk())) { header("Status: 500 How Sad"); die("<h2>Error</h2>Could not fetch POST data.\n"); } #-- decipher incoming XML request string $method = ""; if (XMLRPC_FAST && XMLRPC_EPI) { $params = xmlrpc_decode_request($xml_request, $method); xmlrpc_epi_decode_xtypes($params); } else { $params = xmlrpc_request_unmarshall($xml_request, $method); } #-- add the few system.methods() //if (empty($xmlrpc_methods)) { // $xmlrpc_methods = get_defined_functions(); //} $xmlrpc_methods["system"] = "xmlrpc_system_methods"; # a class #-- call $result = xmlrpc_exec_method($method, $params); #-- send back result if (isset($result)) { if (isset($result)) { $resp["methodResponse"]["params"]["param"] = xmlrpc_compact_value($result); } else { $resp["methodResponse"]["params"] = array(); } xmlrpc_send_response($resp); } else { $result = xmlrpc_error(0, "No Result"); xmlrpc_send_response($result); } }
include "../../inc/includes.php"; Plugin::load('webservices', true); Plugin::doHook("webservices"); plugin_webservices_registerMethods(); error_reporting(E_ALL); if (!array_key_exists('CONTENT_TYPE', $_SERVER) || strpos($_SERVER['CONTENT_TYPE'], 'text/xml') === false) { header("HTTP/1.0 500 Bad content type"); die("Bad content type"); } if (!isset($GLOBALS["HTTP_RAW_POST_DATA"]) || empty($GLOBALS["HTTP_RAW_POST_DATA"])) { header("HTTP/1.0 500 No content"); } $method = ""; $allparams = ""; if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) { $allparams = xmlrpc_decode_request($GLOBALS["HTTP_RAW_POST_DATA"], $method, 'UTF-8'); } if (empty($method) || !is_array($allparams)) { header("HTTP/1.0 500 Bad content"); } $params = isset($allparams[0]) && is_array($allparams[0]) ? $allparams[0] : array(); if (isset($params['iso8859'])) { $iso = true; unset($params['iso8859']); } else { $iso = false; } $session = new PluginWebservicesMethodSession(); $resp = $session->execute($method, $params, WEBSERVICE_PROTOCOL_XMLRPC); header("Content-type: text/xml"); if ($iso) {
$xmlrpcrequest = mnet_server_strip_signature($plaintextmessage); } catch (Exception $e) { mnet_debug('encryption strip exception thrown: ' . $e->getMessage()); exit(mnet_server_fault($e->getCode(), $e->getMessage(), $e->a)); } mnet_debug('XMLRPC Payload', 2); mnet_debug($xmlrpcrequest, 2); if ($remoteclient->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. mnet_debug('sending back new key'); exit(mnet_server_fault_xml(7025, $mnet->public_key, $remoteclient->useprivatekey)); } // Have a peek at what the request would be if we were to process it $params = xmlrpc_decode_request($xmlrpcrequest, $method); mnet_debug("incoming mnet request {$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 ($remoteclient->request_was_encrypted == true && $remoteclient->signatureok == true || ($method == 'system.keyswap' || $method == 'system/keyswap') || $remoteclient->signatureok == true && $remoteclient->plaintext_is_ok() == true) { try { // main dispatch call. will echo the response directly mnet_server_dispatch($xmlrpcrequest); mnet_debug('exiting cleanly'); exit; } catch (Exception $e) { mnet_debug('dispatch exception thrown: ' . $e->getMessage()); exit(mnet_server_fault($e->getCode(), $e->getMessage(), $e->a)); }
source: http://www.securityfocus.com/bid/38708/info PHP's xmlrpc extension library is prone to multiple denial-of-service vulnerabilities because it fails to properly handle crafted XML-RPC requests. Exploiting these issues allows remote attackers to cause denial-of-service conditions in the context of an application using the vulnerable library. PHP 5.3.1 is vulnerable; other versions may also be affected. <?php $req = '<?xml version="1.0"?> <methodCall> </methodCall>'; $result = xmlrpc_decode_request($req, $frop);
/** * Construct this->parameters from POST data * * @since version 9.1 */ public function parseIncomingParams() { $parameters = array(); $resource = ""; $parameters = xmlrpc_decode_request(trim(file_get_contents("php://input")), $resource, 'UTF-8'); $this->parameters = isset($parameters[0]) && is_array($parameters[0]) ? $parameters[0] : array(); // transform input from array to object if (isset($this->parameters['input']) && is_array($this->parameters['input'])) { $first_field = array_values($this->parameters['input'])[0]; if (is_array($first_field)) { foreach ($this->parameters['input'] as &$input) { $input = json_decode(json_encode($input), false); } } else { $this->parameters['input'] = json_decode(json_encode($this->parameters['input']), false); } } return $resource; }
function parseRequest($data = '') { global $HTTP_RAW_POST_DATA; if ($data == '') { $data = $HTTP_RAW_POST_DATA; } // return $this->echoInput($data); /* Decode to extract methodName */ $params = xmlrpc_decode_request($data, &$methName); $this->last_method = $methName; $syscall = 0; /* Setup dispatch map based on the function, if this is a system call */ if (ereg('^system\\.', $methName)) { foreach ($GLOBALS['_xmlrpcs_dmap'] as $meth => $dat) { $this->add_to_map($meth, $dat['function'], $dat['signature'], $dat['docstring']); } $sysCall = 1; $dmap = $this->dmap; } elseif (ereg('^examples\\.', $methName) || ereg('^validator1\\.', $methName) || ereg('^interopEchoTests\\.', $methName)) { $dmap = $this->dmap; $sysCall = 1; } /* verify dispatch map, or try to fix it for non-trivial system calls */ if (!isset($this->dmap[$methName]['function'])) { if ($sysCall) { /* Bad or non-existent system call, return error */ $r = CreateObject('phpgwapi.xmlrpcresp', '', $GLOBALS['xmlrpcerr']['unknown_method'], $GLOBALS['xmlrpcstr']['unknown_method'] . ': ' . $methName); return $r; } if ($this->authed) { $method = $methName; list($app, $class, $method) = explode('.', $methName); switch ($app) { case 'server': case 'phpgwapi': /* Server role functions only - api access */ if ($GLOBALS['phpgw']->acl->get_role() >= PHPGW_ACL_SERVER) { $dmap = ExecMethod(sprintf('%s.%s.%s', 'phpgwapi', $class, 'list_methods'), 'xmlrpc'); } break; case 'service': /* Service functions, user-level */ $t = 'phpgwapi.' . $class . '.exec'; $dmap = ExecMethod($t, array($service, 'list_methods', 'xmlrpc')); break; default: /* User-level application access */ if ($GLOBALS['phpgw']->acl->check('run', PHPGW_ACL_READ, $app)) { $dmap = ExecMethod(sprintf('', $app, $class, 'list_methods'), 'xmlrpc'); } else { $r = CreateObject('phpgwapi.xmlrpcresp', '', $GLOBALS['xmlrpcerr']['no_access'], $GLOBALS['xmlrpcstr']['no_access']); return $r; } } } } /* add the functions from preset $dmap OR list_methods() to the server map */ foreach ($dmap as $meth => $dat) { $this->add_to_map($meth, $dat['function'], $dat['signature'], $dat['docstring']); } /* _debug_array($this->dmap);exit; */ /* Now make the call */ if (isset($dmap[$methName]['function'])) { // dispatch if exists if (isset($dmap[$methName]['signature'])) { $sr = $this->verifySignature($m, $dmap[$methName]['signature']); } if (!isset($dmap[$methName]['signature']) || $sr[0]) { // if no signature or correct signature $r = xmlrpc_server_call_method($this->server, $data, $params); } else { $r = CreateObject('phpgwapi.xmlrpcresp', '', $GLOBALS['xmlrpcerr']['incorrect_params'], $GLOBALS['xmlrpcstr']['incorrect_params'] . ': ' . $sr[1]); } } else { // else prepare error response if (!$this->authed) { // $r = False; // send 401 header to force authorization $r = CreateObject('phpgwapi.xmlrpcresp', CreateObject('phpgwapi.xmlrpcval', 'UNAUTHORIZED', 'string')); } else { $r = CreateObject('phpgwapi.xmlrpcresp', '', $GLOBALS['xmlrpcerr']['unknown_method'], $GLOBALS['xmlrpcstr']['unknown_method'] . ': ' . $methName); } } xmlrpc_server_destroy($xmlrpc_server); return $r; }
/** * This method wraps around xmlrpc_decode_request, since it is borken in many ways. This wraps * around all the ugliness needed to make it not dump core and not print expat warnings. */ private function parseRequest($request_xml) { $xml = @simplexml_load_string($request_xml); if (!$xml && !$xml->getNamespaces()) { // FIXME: check for protocol json-rpc //simplexml in combination with namespaces (soap) lets $xml evaluate to false return xmlrpc_encode_request(null, ripcord::fault(-3, 'Invalid Method Call - Ripcord Server accepts only XML-RPC, SimpleRPC or SOAP 1.1 calls'), $this->outputOptions); } else { // prevent segmentation fault on incorrect xmlrpc request (without methodName) $methodCall = $xml->xpath('//methodCall'); if ($methodCall) { //xml-rpc $methodName = $xml->xpath('//methodName'); if (!$methodName) { return xmlrpc_encode_request(null, ripcord::fault(-3, 'Invalid Method Call - No methodName given'), $this->outputOptions); } } } $method = null; ob_start(); // xmlrpc_decode echo expat errors if the xml is not valid, can't stop it. $params = xmlrpc_decode_request($request_xml, $method); ob_end_clean(); // clean up any xml errors return array('methodName' => $method, 'params' => $params); }
/** * Receive ping, check if local page is pingback-enabled, verify * source contents, and return XML-RPC response * @return string * @param $func callback * @param $path string **/ function listen($func, $path = NULL) { $fw = Base::instance(); if (PHP_SAPI != 'cli') { header('X-Powered-By: ' . $fw->get('PACKAGE')); header('Content-Type: application/xml; ' . 'charset=' . ($charset = $fw->get('ENCODING'))); } if (!$path) { $path = $fw->get('BASE'); } $web = Web::instance(); $args = xmlrpc_decode_request($fw->get('BODY'), $method, $charset); $options = array('encoding' => $charset); if ($method == 'pingback.ping' && isset($args[0], $args[1])) { list($source, $permalink) = $args; $doc = new DOMDocument('1.0', $fw->get('ENCODING')); // Check local page if pingback-enabled $parts = parse_url($permalink); if ((empty($parts['scheme']) || $parts['host'] == $fw->get('HOST')) && preg_match('/^' . preg_quote($path, '/') . '/' . ($fw->get('CASELESS') ? 'i' : ''), $parts['path']) && $this->enabled($permalink)) { // Check source $parts = parse_url($source); if ((empty($parts['scheme']) || $parts['host'] == $fw->get('HOST')) && ($req = $web->request($source)) && $doc->loadhtml($req['body'])) { $links = $doc->getelementsbytagname('a'); foreach ($links as $link) { if ($link->getattribute('href') == $permalink) { call_user_func_array($func, array($source, $req['body'])); // Success die(xmlrpc_encode_request(NULL, $source, $options)); } } // No link to local page die(xmlrpc_encode_request(NULL, 0x11, $options)); } // Source failure die(xmlrpc_encode_request(NULL, 0x10, $options)); } // Doesn't exist (or not pingback-enabled) die(xmlrpc_encode_request(NULL, 0x21, $options)); } // Access denied die(xmlrpc_encode_request(NULL, 0x31, $options)); }
/** * フレームワークの処理を実行する(XMLRPC) * * @access private * @param mixed $action_name 指定のアクション名 * @return mixed 0:正常終了 Ethna_Error:エラー */ function _trigger_XMLRPC($action_name = "") { // prepare xmlrpc server $xmlrpc_gateway_method_name = "_Ethna_XmlrpcGateway"; $xmlrpc_server = xmlrpc_server_create(); $method = null; $param = xmlrpc_decode_request(file_get_contents('php://input'), $method); $this->xmlrpc_method_name = $method; $request = xmlrpc_encode_request($xmlrpc_gateway_method_name, $param, array('output_type' => 'xml', 'verbosity' => 'pretty', 'escaping' => array('markup'), 'version' => 'xmlrpc', 'encoding' => 'utf-8')); xmlrpc_server_register_method($xmlrpc_server, $xmlrpc_gateway_method_name, $xmlrpc_gateway_method_name); // send request $r = xmlrpc_server_call_method($xmlrpc_server, $request, null, array('output_type' => 'xml', 'verbosity' => 'pretty', 'escaping' => array('markup'), 'version' => 'xmlrpc', 'encoding' => 'utf-8')); header('Content-Length: ' . strlen($r)); header('Content-Type: text/xml; charset=UTF-8'); print $r; }