intern->node_list = NULL;
intern->doc = NULL;
intern->profiling = NULL;
- intern->securityPrefs = XSL_SECPREF_WRITE_FILE | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY;
+ intern->securityPrefs = XSL_SECPREF_DEFAULT;
+ intern->securityPrefsSet = 0;
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
}
/* }}} */
+PHP_INI_BEGIN()
+/* Default is not allowing any write operations.
+ XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_WRITE_FILE == 44
+*/
+PHP_INI_ENTRY("xsl.security_prefs", "44", PHP_INI_ALL, NULL)
+PHP_INI_END()
+
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(xsl)
REGISTER_LONG_CONSTANT("XSL_SECPREF_CREATE_DIRECTORY", XSL_SECPREF_CREATE_DIRECTORY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XSL_SECPREF_READ_NETWORK", XSL_SECPREF_READ_NETWORK, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XSL_SECPREF_WRITE_NETWORK", XSL_SECPREF_WRITE_NETWORK, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XSL_SECPREF_DEFAULT", XSL_SECPREF_DEFAULT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("LIBXSLT_VERSION", LIBXSLT_VERSION, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("LIBXSLT_DOTTED_VERSION", LIBXSLT_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("LIBEXSLT_DOTTED_VERSION", LIBEXSLT_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT);
#endif
+ REGISTER_INI_ENTRIES();
+
return SUCCESS;
}
/* }}} */
xsltCleanupGlobals();
+ UNREGISTER_INI_ENTRIES();
+
return SUCCESS;
}
/* }}} */
#define XSL_SECPREF_CREATE_DIRECTORY 8
#define XSL_SECPREF_READ_NETWORK 16
#define XSL_SECPREF_WRITE_NETWORK 32
+/* Default == disable all write access == XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE */
+#define XSL_SECPREF_DEFAULT 44
typedef struct _xsl_object {
zend_object std;
php_libxml_node_object *doc;
char *profiling;
long securityPrefs;
+ int securityPrefsSet;
} xsl_object;
void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
--- /dev/null
+--TEST--
+Bug #54446 (Arbitrary file creation via libxslt 'output' extension with php.ini setting)
+--SKIPIF--
+<?php
+if (!extension_loaded('xsl')) die("skip Extension XSL is required\n");
+?>
+--FILE--
+<?php
+include("prepare.inc");
+
+$outputfile = dirname(__FILE__)."/bug54446test.txt";
+if (file_exists($outputfile)) {
+ unlink($outputfile);
+}
+
+$sXsl = <<<EOT
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:sax="http://icl.com/saxon"
+ extension-element-prefixes="sax">
+
+ <xsl:template match="/">
+ <sax:output href="$outputfile" method="text">
+ <xsl:value-of select="'0wn3d via PHP and libxslt ...'"/>
+ </sax:output>
+ </xsl:template>
+
+</xsl:stylesheet>
+EOT;
+
+$xsl->loadXML( $sXsl );
+
+# START XSLT
+$proc->importStylesheet( $xsl );
+
+# TRASNFORM & PRINT
+print $proc->transformToXML( $dom );
+
+
+if (file_exists($outputfile)) {
+ print "$outputfile exists, but shouldn't!\n";
+} else {
+ print "OK, no file created\n";
+}
+
+#SET NO SECURITY PREFS
+ini_set("xsl.security_prefs", XSL_SECPREF_NONE);
+
+# TRASNFORM & PRINT
+print $proc->transformToXML( $dom );
+
+
+if (file_exists($outputfile)) {
+ print "OK, file exists\n";
+} else {
+ print "$outputfile doesn't exist, but should!\n";
+}
+
+unlink($outputfile);
+
+#SET SECURITY PREFS AGAIN
+ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY);
+
+# TRASNFORM & PRINT
+print $proc->transformToXML( $dom );
+
+if (file_exists($outputfile)) {
+ print "$outputfile exists, but shouldn't!\n";
+} else {
+ print "OK, no file created\n";
+}
+
+#SET NO SECURITY PREFS with ini, but set them with ->setSecurityPrefs
+ini_set("xsl.security_prefs", XSL_SECPREF_NONE);
+$proc->setSecurityPrefs( XSL_SECPREF_WRITE_FILE | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY);
+
+print $proc->transformToXML( $dom );
+if (file_exists($outputfile)) {
+ print "$outputfile exists, but shouldn't!\n";
+} else {
+ print "OK, no file created\n";
+}
+
+#don't throw a warning if both ini and through-the-method have the same value
+$proc->setSecurityPrefs(XSL_SECPREF_NONE);
+
+print $proc->transformToXML( $dom );
+
+if (file_exists($outputfile)) {
+ print "OK, file exists\n";
+} else {
+ print "$outputfile doesn't exist, but should!\n";
+}
+unlink($outputfile);
+
+
+
+--EXPECTF--
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
+OK, no file created
+
+Deprecated: XSLTProcessor::transformToXml(): The xsl.security_prefs php.ini option is deprecated; use XsltProcessor->setSecurityPrefs() instead in %s on line %d
+OK, file exists
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
+OK, no file created
+
+Deprecated: XSLTProcessor::transformToXml(): The xsl.security_prefs php.ini option is deprecated; use XsltProcessor->setSecurityPrefs() instead in %s on line %d
+
+Notice: XSLTProcessor::transformToXml(): The xsl.security_prefs php.ini was not used, since the XsltProcessor->setSecurityPrefs() method was used in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
+OK, no file created
+OK, file exists
+--CREDITS--
+Christian Stocker, chregu@php.net
+
zend_object_handlers *std_hnd;
FILE *f;
int secPrefsError = 0;
+ int secPrefsValue, secPrefsIni;
xsltSecurityPrefsPtr secPrefs = NULL;
node = php_libxml_import_node(docp TSRMLS_CC);
}
efree(member);
+ secPrefsValue = intern->securityPrefs;
- //if securityPrefs is set to NONE, we don't have to do any checks, but otherwise...
- if (intern->securityPrefs != XSL_SECPREF_NONE) {
+ /* This whole if block can be removed, when we remove the xsl.security_prefs php.ini option in PHP 6+ */
+ secPrefsIni= INI_INT("xsl.security_prefs");
+ /* if secPrefsIni has the same value as secPrefsValue, all is fine */
+ if (secPrefsIni != secPrefsValue) {
+ if (secPrefsIni != XSL_SECPREF_DEFAULT) {
+ /* if the ini value is not set to the default, throw an E_DEPRECATED warning */
+ php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "The xsl.security_prefs php.ini option is deprecated; use XsltProcessor->setSecurityPrefs() instead");
+ if (intern->securityPrefsSet == 0) {
+ /* if securityPrefs were not set through the setSecurityPrefs method, take the ini setting */
+ secPrefsValue = secPrefsIni;
+ } else {
+ /* else throw a notice, that the ini setting was not used */
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The xsl.security_prefs php.ini was not used, since the XsltProcessor->setSecurityPrefs() method was used");
+ }
+ }
+ }
+
+ /* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */
+ if (secPrefsValue != XSL_SECPREF_NONE) {
secPrefs = xsltNewSecurityPrefs();
- if (intern->securityPrefs & XSL_SECPREF_READ_FILE ) {
+ if (secPrefsValue & XSL_SECPREF_READ_FILE ) {
if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (intern->securityPrefs & XSL_SECPREF_WRITE_FILE ) {
+ if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) {
if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (intern->securityPrefs & XSL_SECPREF_CREATE_DIRECTORY ) {
+ if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) {
if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (intern->securityPrefs & XSL_SECPREF_READ_NETWORK) {
+ if (secPrefsValue & XSL_SECPREF_READ_NETWORK) {
if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) {
secPrefsError = 1;
}
}
- if (intern->securityPrefs & XSL_SECPREF_WRITE_NETWORK) {
+ if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) {
if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) {
secPrefsError = 1;
}
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
oldSecurityPrefs = intern->securityPrefs;
intern->securityPrefs = securityPrefs;
+ /* set this to 1 so that we know, it was set through this method. Can be removed, when we remove the ini setting */
+ intern->securityPrefsSet = 1;
RETURN_LONG(oldSecurityPrefs);
}
/* }}} end xsl_xsltprocessor_set_security_prefs */