Skip to content

Commit

Permalink
ext/soap: Don't call readfile() userland function (#17432)
Browse files Browse the repository at this point in the history
* ext/soap: Add some SoapServer tests

* ext/soap: Don't call readfile() userland function

We can perform the operation directly, moreover there is no risk of a user disabling the readfile function and defining their own messing up what we are doing.

* ext/soap: Actually throw a SOAP Fault if the WSDL has disappeared
  • Loading branch information
Girgias authored Jan 15, 2025
1 parent 7512685 commit b7169a2
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 8 deletions.
14 changes: 6 additions & 8 deletions ext/soap/soap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1307,19 +1307,17 @@ PHP_METHOD(SoapServer, handle)
sapi_add_header(hdr, sizeof("Location: ")+strlen(service->sdl->source)-1, 1);
efree(hdr);
*/
zval readfile, readfile_ret, param;

sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
ZVAL_STRING(&param, service->sdl->source);
ZVAL_STRING(&readfile, "readfile");
if (call_user_function(EG(function_table), NULL, &readfile, &readfile_ret, 1, &param ) == FAILURE) {
php_stream_context *context = php_stream_context_from_zval(NULL, false);
php_stream *stream = php_stream_open_wrapper_ex(service->sdl->source, "rb", REPORT_ERRORS, NULL, context);
if (stream) {
php_stream_passthru(stream);
php_stream_close(stream);
} else {
soap_server_fault("Server", "Couldn't find WSDL", NULL, NULL, NULL);
}

zval_ptr_dtor(&param);
zval_ptr_dtor_str(&readfile);
zval_ptr_dtor(&readfile_ret);

SOAP_SERVER_END_CODE();
return;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
--TEST--
SoapServer handle with WSDL that has disappeared
--EXTENSIONS--
soap
--SKIPIF--
<?php
if (PHP_OS_FAMILY === "Windows") {
die("skip see https://github.com/php/php-src/issues/17468");
}
?>
--GET--
WSDL
--FILE--
<?php
$wsdlFile = __DIR__ . '/test_handle_non_existent_wsdl_from_get_query.wsdl';

$wsdl = <<<'WSDL'
<?xml version="1.0" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<xsd:schema targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
<message name="AddRequest">
<part name="x" type="xsd:double" />
<part name="y" type="xsd:double" />
</message>
<message name="AddResponse">
<part name="result" type="xsd:double" />
</message>
<portType name="TestServicePortType">
<operation name="Add">
<input message="tns:AddRequest" />
<output message="tns:AddResponse" />
</operation>
</portType>
<binding name="TestServiceBinding" type="tns:TestServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="Add">
<soap:operation soapAction="Add" style="rpc" />
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>
<service name="TestService">
<port name="TestServicePort" binding="tns:TestServiceBinding">
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
</port>
</service>
</definitions>
WSDL;

file_put_contents($wsdlFile, $wsdl);

$options = [];
$server = new SoapServer($wsdlFile, $options);

unlink($wsdlFile);

$server->handle();

?>
--CLEAN--
<?php
$wsdlFile = __DIR__ . '/test_handle_non_existent_wsdl_from_get_query.wsdl';
@unlink($wsdlFile);
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Couldn't find WSDL</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
--TEST--
SoapServer handle with WSDL that has disappeared and disabled readfile function
--EXTENSIONS--
soap
--SKIPIF--
<?php
if (PHP_OS_FAMILY === "Windows") {
die("skip see https://github.com/php/php-src/issues/17468");
}
?>
--GET--
WSDL
--INI--
disable_functions=readfile
--FILE--
<?php
$wsdlFile = __DIR__ . '/test_handle_non_existent_wsdl_from_get_query_disable_readfile.wsdl';

$wsdl = <<<'WSDL'
<?xml version="1.0" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<xsd:schema targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
<message name="AddRequest">
<part name="x" type="xsd:double" />
<part name="y" type="xsd:double" />
</message>
<message name="AddResponse">
<part name="result" type="xsd:double" />
</message>
<portType name="TestServicePortType">
<operation name="Add">
<input message="tns:AddRequest" />
<output message="tns:AddResponse" />
</operation>
</portType>
<binding name="TestServiceBinding" type="tns:TestServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="Add">
<soap:operation soapAction="Add" style="rpc" />
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>
<service name="TestService">
<port name="TestServicePort" binding="tns:TestServiceBinding">
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
</port>
</service>
</definitions>
WSDL;

file_put_contents($wsdlFile, $wsdl);

$options = [];
$server = new SoapServer($wsdlFile, $options);

unlink($wsdlFile);
$server->handle();

?>
--CLEAN--
<?php
$wsdlFile = __DIR__ . '/test_handle_non_existent_wsdl_from_get_query_disable_readfile.wsdl';
@unlink($wsdlFile);
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Couldn't find WSDL</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

0 comments on commit b7169a2

Please sign in to comment.