1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-07-10 14:40:58 +03:00

new module with runtime security checks, it will also check and do

* libxslt/security.[ch] libxslt/Makefile.am: new module with
  runtime security checks, it will also check and do directory
  creation when allowed
* libxslt/documents.c libxslt/imports.c libxslt/transform.c
  libxslt/xslt.c libxslt/xsltInternals.h: plug-in the new
  security infrastructure probes at file reading or file creation
* xsltproc/xsltproc.c: plugged the security module there too,
  added the new options --nowrite and --nomkdir
* doc/*: updated the man page and regenerated.
Daniel
This commit is contained in:
Daniel Veillard
2002-10-10 15:26:25 +00:00
parent 2ae9ba850c
commit 159d00a5a0
16 changed files with 771 additions and 2 deletions

View File

@ -1,3 +1,15 @@
Thu Oct 10 17:16:52 CEST 2002 Daniel Veillard <daniel@veillard.com>
* libxslt/security.[ch] libxslt/Makefile.am: new module with
runtime security checks, it will also check and do directory
creation when allowed
* libxslt/documents.c libxslt/imports.c libxslt/transform.c
libxslt/xslt.c libxslt/xsltInternals.h: plug-in the new
security infrastructure probes at file reading or file creation
* xsltproc/xsltproc.c: plugged the security module there too,
added the new options --nowrite and --nomkdir
* doc/*: updated the man page and regenerated.
Wed Oct 9 18:37:56 CEST 2002 Daniel Veillard <daniel@veillard.com>
* doc/*: updated the doc XSLT to add the search, added the search

View File

@ -2364,7 +2364,7 @@ HREF="libxslt-xsltinternals.html#XSLTSTYLEPRECOMPPTR"
></TR
></TABLE
><P
>Process an XSLT-1.1 document element</P
>Process an EXSLT/XSLT-1.1 document element</P
><P
></P
><DIV

View File

@ -1084,6 +1084,7 @@ CLASS="PROGRAMLISTING"
xsltRuntimeExtraPtr extras; /* extra per runtime informations */
xsltDocumentPtr styleList; /* the stylesheet docs list */
void * sec; /* the security preferences if any */
};</PRE
></TD
></TR

View File

@ -1087,6 +1087,85 @@ void
<NAME>LIBXSLT_PUBLIC</NAME>
#define LIBXSLT_PUBLIC
</MACRO>
<STRUCT>
<NAME>xsltSecurityPrefs</NAME>
</STRUCT>
<TYPEDEF>
<NAME>xsltSecurityPrefsPtr</NAME>
typedef xsltSecurityPrefs *xsltSecurityPrefsPtr;
</TYPEDEF>
<ENUM>
<NAME>xsltSecurityOption</NAME>
typedef enum {
XSLT_SECPREF_READ_FILE = 1,
XSLT_SECPREF_WRITE_FILE,
XSLT_SECPREF_CREATE_DIRECTORY,
XSLT_SECPREF_READ_NETWORK,
XSLT_SECPREF_WRITE_NETWORK
} xsltSecurityOption;
</ENUM>
<USER_FUNCTION>
<NAME>xsltSecurityCheck</NAME>
<RETURNS>int </RETURNS>
xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt,
const char *value
</USER_FUNCTION>
<FUNCTION>
<NAME>xsltNewSecurityPrefs</NAME>
<RETURNS>xsltSecurityPrefsPtr </RETURNS>
void
</FUNCTION>
<FUNCTION>
<NAME>xsltFreeSecurityPrefs</NAME>
<RETURNS>void </RETURNS>
xsltSecurityPrefsPtr sec
</FUNCTION>
<FUNCTION>
<NAME>xsltSetSecurityPrefs</NAME>
<RETURNS>int </RETURNS>
xsltSecurityPrefsPtr sec,xsltSecurityOption option,xsltSecurityCheck func
</FUNCTION>
<FUNCTION>
<NAME>xsltGetSecurityPrefs</NAME>
<RETURNS>xsltSecurityCheck </RETURNS>
xsltSecurityPrefsPtr sec,xsltSecurityOption option
</FUNCTION>
<FUNCTION>
<NAME>xsltSetDefaultSecurityPrefs</NAME>
<RETURNS>void </RETURNS>
xsltSecurityPrefsPtr sec
</FUNCTION>
<FUNCTION>
<NAME>xsltGetDefaultSecurityPrefs</NAME>
<RETURNS>xsltSecurityPrefsPtr </RETURNS>
void
</FUNCTION>
<FUNCTION>
<NAME>xsltSetCtxtSecurityPrefs</NAME>
<RETURNS>int </RETURNS>
xsltSecurityPrefsPtr sec,xsltTransformContextPtr ctxt
</FUNCTION>
<FUNCTION>
<NAME>xsltSecurityAllow</NAME>
<RETURNS>int </RETURNS>
xsltSecurityPrefsPtr sec,xsltTransformContextPtr ctxt,const char *value
</FUNCTION>
<FUNCTION>
<NAME>xsltSecurityForbid</NAME>
<RETURNS>int </RETURNS>
xsltSecurityPrefsPtr sec,xsltTransformContextPtr ctxt,const char *value
</FUNCTION>
<FUNCTION>
<NAME>xsltCheckWrite</NAME>
<RETURNS>int </RETURNS>
xsltSecurityPrefsPtr sec,xsltTransformContextPtr ctxt,const xmlChar *URL
</FUNCTION>
<FUNCTION>
<NAME>xsltCheckRead</NAME>
<RETURNS>int </RETURNS>
xsltSecurityPrefsPtr sec,xsltTransformContextPtr ctxt,const xmlChar *URL
</FUNCTION>
<MACRO>
<NAME>XSLT_MAX_SORT</NAME>
#define XSLT_MAX_SORT 5
@ -1525,6 +1604,7 @@ struct xsltTransformContext {
xsltRuntimeExtraPtr extras; /* extra per runtime informations */
xsltDocumentPtr styleList; /* the stylesheet docs list */
void * sec; /* the security preferences if any */
};
</STRUCT>
<MACRO>

View File

@ -283,6 +283,25 @@ ATTRIBUTE_UNUSED
LIBXSLT_PUBLIC
</SECTION>
<SECTION>
<FILE>security</FILE>
xsltSecurityPrefs
xsltSecurityPrefsPtr
xsltSecurityOption
xsltSecurityCheck
xsltNewSecurityPrefs
xsltFreeSecurityPrefs
xsltSetSecurityPrefs
xsltGetSecurityPrefs
xsltSetDefaultSecurityPrefs
xsltGetDefaultSecurityPrefs
xsltSetCtxtSecurityPrefs
xsltSecurityAllow
xsltSecurityForbid
xsltCheckWrite
xsltCheckRead
</SECTION>
<SECTION>
<FILE>xsltInternals</FILE>
XSLT_MAX_SORT

View File

@ -28,6 +28,7 @@ xsltproc \- command line xslt processor
| \fB--html\fR | \fB--docbook\fR | \fB--param \fIname\fR \fIvalue\fR\fR
| \fB--stringparam \fIname\fR \fIvalue\fR\fR | \fB--nonet\fR | \fB--catalogs\fR
| \fB--xinclude\fR | \fB--profile\fR | \fB--dumpextensions\fR] [\fBstylesheet\fR]
| \fB--nowrite\fR | \fB--nomkdir\fR
[\fIfile1\fR] [\fIfile2\fR] [\fI....\fR]
.fi
@ -119,6 +120,14 @@ Output profiling information detailing the amount of time spent in each part of
\fB--dumpextensions\fR
Dumps the list of all registered extensions on stdout.
.TP
\fB--nowrite\fR
Refuses to write to any file or resource.
.TP
\fB--nomkdir\fR
Refuses to create directories.
.SH "RETURN VALUES"
.PP

View File

@ -50,6 +50,8 @@
<arg>--xinclude</arg>
<arg>--profile</arg>
<arg>--dumpextensions</arg>
<arg>--nowrite</arg>
<arg>--nomkdir</arg>
</group>
<arg><option><replaceable>stylesheet</replaceable></option></arg>
<arg><replaceable>file1</replaceable></arg>
@ -299,6 +301,24 @@
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--nowrite</option></term>
<listitem>
<simpara>Refuses to write to any file or resource.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--nomkdir</option></term>
<listitem>
<simpara>Refuses to create directories.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -21,6 +21,7 @@ xsltinc_HEADERS = \
documents.h \
preproc.h \
transform.h \
security.h \
xsltInternals.h \
xsltconfig.h
@ -41,6 +42,7 @@ libxslt_la_SOURCES = \
documents.c \
preproc.c \
transform.c \
security.c \
win32config.h \
xsltwin32config.h \
xsltwin32config.h.in \

View File

@ -21,6 +21,7 @@
#include "transform.h"
#include "imports.h"
#include "keys.h"
#include "security.h"
#ifdef LIBXML_XINCLUDE_ENABLED
#include <libxml/xinclude.h>
@ -163,6 +164,22 @@ xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
if ((ctxt == NULL) || (URI == NULL))
return(NULL);
/*
* Security framework check
*/
if (ctxt->sec != NULL) {
int res;
res = xsltCheckRead(ctxt->sec, ctxt, URI);
if (res == 0) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltLoadDocument: read rights for %s denied\n",
URI);
return(NULL);
}
}
/*
* Walk the context list to find the document if preparsed
*/
@ -211,10 +228,28 @@ xsltDocumentPtr
xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
xsltDocumentPtr ret;
xmlDocPtr doc;
xsltSecurityPrefsPtr sec;
if ((style == NULL) || (URI == NULL))
return(NULL);
/*
* Security framework check
*/
sec = xsltGetDefaultSecurityPrefs();
if (sec != NULL) {
int res;
res = xsltCheckRead(sec, NULL, URI);
if (res == 0) {
xsltPrintErrorContext(NULL, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltLoadStyleDocument: read rights for %s denied\n",
URI);
return(NULL);
}
}
/*
* Walk the context list to find the document if preparsed
*/

View File

@ -43,6 +43,7 @@
#include "xsltutils.h"
#include "imports.h"
#include "documents.h"
#include "security.h"
@ -70,6 +71,7 @@ xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
xmlChar *uriRef = NULL;
xmlChar *URI = NULL;
xsltStylesheetPtr res;
xsltSecurityPrefsPtr sec;
if ((cur == NULL) || (style == NULL))
return (ret);
@ -90,6 +92,24 @@ xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
"xsl:import : invalid URI reference %s\n", uriRef);
goto error;
}
/*
* Security framework check
*/
sec = xsltGetDefaultSecurityPrefs();
if (sec != NULL) {
int res;
res = xsltCheckRead(sec, NULL, URI);
if (res == 0) {
xsltPrintErrorContext(NULL, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsl:import: read rights for %s denied\n",
URI);
goto error;
}
}
import = xmlParseFile((const char *)URI);
if (import == NULL) {
xsltPrintErrorContext(NULL, style, cur);

429
libxslt/security.c Normal file
View File

@ -0,0 +1,429 @@
/*
* security.c: Implementation of the XSLT security framework
*
* See Copyright for the status of this software.
*
* daniel@veillard.com
*/
#define IN_LIBXSLT
#include "libxslt.h"
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_MATH_H
#include <math.h>
#endif
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
#ifdef HAVE_NAN_H
#include <nan.h>
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/uri.h>
#include "xslt.h"
#include "xsltInternals.h"
#include "xsltutils.h"
#include "security.h"
struct _xsltSecurityPrefs {
xsltSecurityCheck readFile;
xsltSecurityCheck createFile;
xsltSecurityCheck createDir;
xsltSecurityCheck readNet;
xsltSecurityCheck writeNet;
};
static xsltSecurityPrefsPtr xsltDefaultSecurityPrefs = NULL;
/************************************************************************
* *
* Module interfaces *
* *
************************************************************************/
/**
* xsltNewSecurityPrefs:
*
* Create a new security preference block
*
* Returns a pointer to the new block or NULL in case of error
*/
xsltSecurityPrefsPtr
xsltNewSecurityPrefs(void) {
xsltSecurityPrefsPtr ret;
ret = (xsltSecurityPrefsPtr) xmlMalloc(sizeof(xsltSecurityPrefs));
if (ret == NULL) {
xsltPrintErrorContext(NULL, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltNewSecurityPrefs : malloc failed\n");
return(NULL);
}
memset(ret, 0, sizeof(xsltSecurityPrefs));
return(ret);
}
/**
* xsltFreeSecurityPrefs:
* @sec: the security block to free
*
* Free up a security preference block
*/
void
xsltFreeSecurityPrefs(xsltSecurityPrefsPtr sec) {
if (sec == NULL)
return;
xmlFree(sec);
}
/**
* xsltSetSecurityPrefs:
* @sec: the security block to update
* @option: the option to update
* @func: the user callback to use for this option
*
* Update the security option to use the new callback checking function
*
* Returns -1 in case of error, 0 otherwise
*/
int
xsltSetSecurityPrefs(xsltSecurityPrefsPtr sec, xsltSecurityOption option,
xsltSecurityCheck func) {
if (sec == NULL)
return(-1);
switch (option) {
case XSLT_SECPREF_READ_FILE:
sec->readFile = func; return(0);
case XSLT_SECPREF_WRITE_FILE:
sec->createFile = func; return(0);
case XSLT_SECPREF_CREATE_DIRECTORY:
sec->createDir = func; return(0);
case XSLT_SECPREF_READ_NETWORK:
sec->readNet = func; return(0);
case XSLT_SECPREF_WRITE_NETWORK:
sec->writeNet = func; return(0);
}
return(-1);
}
/**
* xsltGetSecurityPrefs:
* @sec: the security block to update
* @option: the option to lookup
*
* Lookup the security option to get the callback checking function
*
* Returns NULL if not found, the function otherwise
*/
xsltSecurityCheck
xsltGetSecurityPrefs(xsltSecurityPrefsPtr sec, xsltSecurityOption option) {
if (sec == NULL)
return(NULL);
switch (option) {
case XSLT_SECPREF_READ_FILE:
return(sec->readFile);
case XSLT_SECPREF_WRITE_FILE:
return(sec->createFile);
case XSLT_SECPREF_CREATE_DIRECTORY:
return(sec->createDir);
case XSLT_SECPREF_READ_NETWORK:
return(sec->readNet);
case XSLT_SECPREF_WRITE_NETWORK:
return(sec->writeNet);
}
return(NULL);
}
/**
* xsltSetDefaultSecurityPrefs:
* @sec: the security block to use
*
* Set the default security preference application-wide
*/
void
xsltSetDefaultSecurityPrefs(xsltSecurityPrefsPtr sec) {
xsltDefaultSecurityPrefs = sec;
}
/**
* xsltSetDefaultSecurityPrefs:
*
* Get the default security preference application-wide
*
* Returns the current xsltSecurityPrefsPtr in use or NULL if none
*/
xsltSecurityPrefsPtr
xsltGetDefaultSecurityPrefs(void) {
return(xsltDefaultSecurityPrefs);
}
/**
* xsltSetCtxtSecurityPrefs:
* @sec: the security block to use
* @ctxt: an XSLT transformation context
*
* Set the security preference for a specific transformation
*
* Returns -1 in case of error, 0 otherwise
*/
int
xsltSetCtxtSecurityPrefs(xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt) {
if (ctxt == NULL)
return(-1);
ctxt->sec = (void *) sec;
return(0);
}
/**
* xsltSecurityAllow:
* @sec: the security block to use
* @ctxt: an XSLT transformation context
* @value: unused
*
* Function used to always allow an operation
*
* Returns 1 always
*/
int
xsltSecurityAllow(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED,
xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
const char *value ATTRIBUTE_UNUSED) {
return(1);
}
/**
* xsltSecurityForbid:
* @sec: the security block to use
* @ctxt: an XSLT transformation context
* @value: unused
*
* Function used to always forbid an operation
*
* Returns 0 always
*/
int
xsltSecurityForbid(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED,
xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
const char *value ATTRIBUTE_UNUSED) {
return(0);
}
/************************************************************************
* *
* Internal interfaces *
* *
************************************************************************/
/**
* xsltCheckFilename
* @path: the path to check
*
* function checks to see if @path is a valid source
* (file, socket...) for XML.
*
* TODO: remove at some point !!!
* Local copy of xmlCheckFilename to avoid a hard dependancy on
* a new version of libxml2
*
* if stat is not available on the target machine,
* returns 1. if stat fails, returns 0 (if calling
* stat on the filename fails, it can't be right).
* if stat succeeds and the file is a directory,
* returns 2. otherwise returns 1.
*/
static int
xsltCheckFilename (const char *path)
{
#ifdef HAVE_STAT
struct stat stat_buffer;
if (stat(path, &stat_buffer) == -1)
return 0;
#ifdef S_ISDIR
if (S_ISDIR(stat_buffer.st_mode)) {
return 2;
}
#endif
#endif
return 1;
}
/**
* xsltCheckWrite:
* @sec: the security options
* @ctxt: an XSLT transformation context
* @URL: the resource to be written
*
* Check if the resource is allowed to be written, if necessary makes
* some preliminary work like creating directories
*
* Return 1 if write is allowed, 0 if not and -1 in case or error.
*/
int
xsltCheckWrite(xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt, const xmlChar *URL) {
int ret;
xmlURIPtr uri;
xsltSecurityCheck check;
uri = xmlParseURI((const char *)URL);
if (uri == NULL) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltDocumentElem: URL parsing failed for %s\n",
URL);
return(-1);
}
if ((uri->scheme == NULL) ||
(xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
char *directory;
/*
* Check if we are allowed to write this file
*/
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE);
if (check != NULL) {
ret = check(sec, ctxt, uri->path);
if (ret == 0) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"File write for %s refused\n", URL);
xmlFreeURI(uri);
return(0);
}
}
directory = xmlParserGetDirectory (uri->path);
if (directory != NULL) {
ret = xsltCheckFilename(directory);
if (ret == 0) {
/*
* The directory doesn't exist check for creation
*/
check = xsltGetSecurityPrefs(sec,
XSLT_SECPREF_CREATE_DIRECTORY);
if (check != NULL) {
ret = check(sec, ctxt, directory);
if (ret == 0) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"Directory creation for %s refused\n",
URL);
xmlFree(directory);
xmlFreeURI(uri);
return(0);
}
}
ret = xsltCheckWrite(sec, ctxt, (const xmlChar *)directory);
if (ret == 1)
ret = mkdir(directory, 0755);
if (ret < 0)
return(ret);
}
xmlFree(directory);
}
} else {
/*
* Check if we are allowed to write this network resource
*/
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_WRITE_NETWORK);
if (check != NULL) {
ret = check(sec, ctxt, uri->path);
if (ret == 0) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"File write for %s refused\n", URL);
xmlFreeURI(uri);
return(0);
}
}
}
xmlFreeURI(uri);
return(1);
}
/**
* xsltCheckRead:
* @sec: the security options
* @ctxt: an XSLT transformation context
* @URL: the resource to be read
*
* Check if the resource is allowed to be read
*
* Return 1 if read is allowed, 0 if not and -1 in case or error.
*/
int
xsltCheckRead(xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt, const xmlChar *URL) {
int ret;
xmlURIPtr uri;
xsltSecurityCheck check;
uri = xmlParseURI((const char *)URL);
if (uri == NULL) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltCheckRead: URL parsing failed for %s\n",
URL);
return(-1);
}
if ((uri->scheme == NULL) ||
(xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
/*
* Check if we are allowed to read this file
*/
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_READ_FILE);
if (check != NULL) {
ret = check(sec, ctxt, uri->path);
if (ret == 0) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"Local file read for %s refused\n", URL);
xmlFreeURI(uri);
return(0);
}
}
} else {
/*
* Check if we are allowed to write this network resource
*/
check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_READ_NETWORK);
if (check != NULL) {
ret = check(sec, ctxt, uri->path);
if (ret == 0) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"Network file read for %s refused\n", URL);
xmlFreeURI(uri);
return(0);
}
}
}
xmlFreeURI(uri);
return(1);
}

89
libxslt/security.h Normal file
View File

@ -0,0 +1,89 @@
/*
* security.h: interface for the XSLT security framework
*
* See Copyright for the status of this software.
*
* daniel@veillard.com
*/
#ifndef __XML_XSLT_SECURITY_H__
#define __XML_XSLT_SECURITY_H__
#include <libxml/tree.h>
#include "xsltInternals.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* xsltSecurityPref:
*
* structure to indicate the preferences for security in the XSLT
* transformation.
*/
typedef struct _xsltSecurityPrefs xsltSecurityPrefs;
typedef xsltSecurityPrefs *xsltSecurityPrefsPtr;
/**
* xsltSecurityOption:
*
* the set of option that can be configured
*/
typedef enum {
XSLT_SECPREF_READ_FILE = 1,
XSLT_SECPREF_WRITE_FILE,
XSLT_SECPREF_CREATE_DIRECTORY,
XSLT_SECPREF_READ_NETWORK,
XSLT_SECPREF_WRITE_NETWORK
} xsltSecurityOption;
/**
* xsltSecurityCheck:
*
* User provided function to check the value of a string like a file
* path or an URL ...
*/
typedef int (*xsltSecurityCheck) (xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt,
const char *value);
/*
* Module interfaces
*/
xsltSecurityPrefsPtr xsltNewSecurityPrefs (void);
void xsltFreeSecurityPrefs (xsltSecurityPrefsPtr sec);
int xsltSetSecurityPrefs (xsltSecurityPrefsPtr sec,
xsltSecurityOption option,
xsltSecurityCheck func);
xsltSecurityCheck xsltGetSecurityPrefs (xsltSecurityPrefsPtr sec,
xsltSecurityOption option);
void xsltSetDefaultSecurityPrefs(xsltSecurityPrefsPtr sec);
xsltSecurityPrefsPtr xsltGetDefaultSecurityPrefs(void);
int xsltSetCtxtSecurityPrefs(xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt);
int xsltSecurityAllow (xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt,
const char *value);
int xsltSecurityForbid (xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt,
const char *value);
/*
* internal interfaces
*/
int xsltCheckWrite (xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt,
const xmlChar *URL);
int xsltCheckRead (xsltSecurityPrefsPtr sec,
xsltTransformContextPtr ctxt,
const xmlChar *URL);
#ifdef __cplusplus
}
#endif
#endif /* __XML_XSLT_SECURITY_H__ */

View File

@ -50,6 +50,7 @@
#include "extensions.h"
#include "extra.h"
#include "preproc.h"
#include "security.h"
#ifdef WITH_XSLT_DEBUG
#define WITH_XSLT_DEBUG_EXTRA
@ -290,6 +291,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
cur->inst = NULL;
cur->xinclude = xsltDoXIncludeDefault;
cur->outputFile = NULL;
cur->sec = xsltGetDefaultSecurityPrefs();
return(cur);
}
@ -1526,7 +1528,7 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
* @inst: the instruction in the stylesheet
* @comp: precomputed information
*
* Process an XSLT-1.1 document element
* Process an EXSLT/XSLT-1.1 document element
*/
void
xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
@ -1621,6 +1623,18 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlFree(URL);
return;
}
if (ctxt->sec != NULL) {
ret = xsltCheckWrite(ctxt->sec, ctxt, filename);
if (ret == 0) {
xsltPrintErrorContext(ctxt, NULL, inst);
xsltGenericError(xsltGenericErrorContext,
"xsltDocumentElem: write rights for %s denied\n",
filename);
xmlFree(URL);
xmlFree(filename);
return;
}
}
oldOutputFile = ctxt->outputFile;
oldOutput = ctxt->output;

View File

@ -40,6 +40,7 @@
#include "extensions.h"
#include "preproc.h"
#include "extra.h"
#include "security.h"
#ifdef WITH_XSLT_DEBUG
#define WITH_XSLT_DEBUG_PARSING
@ -1992,6 +1993,7 @@ xsltParseStylesheetDoc(xmlDocPtr doc) {
xsltStylesheetPtr
xsltParseStylesheetFile(const xmlChar* filename) {
xsltSecurityPrefsPtr sec;
xsltStylesheetPtr ret;
xmlDocPtr doc;
@ -2004,6 +2006,23 @@ xsltParseStylesheetFile(const xmlChar* filename) {
"xsltParseStylesheetFile : parse %s\n", filename);
#endif
/*
* Security framework check
*/
sec = xsltGetDefaultSecurityPrefs();
if (sec != NULL) {
int res;
res = xsltCheckRead(sec, NULL, filename);
if (res == 0) {
xsltPrintErrorContext(NULL, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltParseStylesheetFile: read rights for %s denied\n",
filename);
return(NULL);
}
}
doc = xmlParseFile((const char *) filename);
if (doc == NULL) {
xsltPrintErrorContext(NULL, NULL, NULL);

View File

@ -455,6 +455,7 @@ struct _xsltTransformContext {
xsltRuntimeExtraPtr extras; /* extra per runtime informations */
xsltDocumentPtr styleList; /* the stylesheet docs list */
void * sec; /* the security preferences if any */
};
/**

View File

@ -49,6 +49,7 @@
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libxslt/extensions.h>
#include <libxslt/security.h>
#include <libexslt/exsltconfig.h>
@ -381,6 +382,8 @@ static void usage(const char *name) {
printf("\t use stringparam to avoid it\n");
printf("\t--stringparam name value : pass a (parameter, UTF8 string value) pair\n");
printf("\t--nonet refuse to fetch DTDs or entities over network\n");
printf("\t--nowrite refuse to write to any file or resource\n");
printf("\t--nomkdir refuse to create directories\n");
#ifdef LIBXML_CATALOG_ENABLED
printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
printf("\t otherwise XML Catalogs starting from \n");
@ -400,6 +403,7 @@ main(int argc, char **argv)
int i;
xsltStylesheetPtr cur = NULL;
xmlDocPtr doc, style;
xsltSecurityPrefsPtr sec = NULL;
if (argc <= 1) {
usage(argv[0]);
@ -411,6 +415,8 @@ main(int argc, char **argv)
LIBXML_TEST_VERSION
xmlLineNumbersDefault(1);
sec = xsltNewSecurityPrefs();
xsltSetDefaultSecurityPrefs(sec);
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-"))
@ -478,6 +484,18 @@ main(int argc, char **argv)
} else if ((!strcmp(argv[i], "-nonet")) ||
(!strcmp(argv[i], "--nonet"))) {
xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
} else if ((!strcmp(argv[i], "-nowrite")) ||
(!strcmp(argv[i], "--nowrite"))) {
xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE,
xsltSecurityForbid);
xsltSetSecurityPrefs(sec, XSLT_SECPREF_CREATE_DIRECTORY,
xsltSecurityForbid);
xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_NETWORK,
xsltSecurityForbid);
} else if ((!strcmp(argv[i], "-nomkdir")) ||
(!strcmp(argv[i], "--nomkdir"))) {
xsltSetSecurityPrefs(sec, XSLT_SECPREF_CREATE_DIRECTORY,
xsltSecurityForbid);
#ifdef LIBXML_CATALOG_ENABLED
} else if ((!strcmp(argv[i], "-catalogs")) ||
(!strcmp(argv[i], "--catalogs"))) {
@ -679,6 +697,7 @@ done:
#if 0
xmlMemoryDump();
#endif
xsltFreeSecurityPrefs(sec);
return(errorno);
}