VirtualBox

source: vbox/trunk/src/libs/libxslt-1.1.22/libxslt/security.c@ 12198

Last change on this file since 12198 was 7296, checked in by vboxsync, 17 years ago

Added libxslt-1.1.22 sources.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 10.9 KB
Line 
1/*
2 * security.c: Implementation of the XSLT security framework
3 *
4 * See Copyright for the status of this software.
5 *
6 * daniel@veillard.com
7 */
8
9#define IN_LIBXSLT
10#include "libxslt.h"
11
12#include <string.h>
13
14#ifdef HAVE_SYS_TYPES_H
15#include <sys/types.h>
16#endif
17#ifdef HAVE_SYS_STAT_H
18#include <sys/stat.h>
19#endif
20
21#ifdef HAVE_MATH_H
22#include <math.h>
23#endif
24#ifdef HAVE_FLOAT_H
25#include <float.h>
26#endif
27#ifdef HAVE_IEEEFP_H
28#include <ieeefp.h>
29#endif
30#ifdef HAVE_NAN_H
31#include <nan.h>
32#endif
33#ifdef HAVE_CTYPE_H
34#include <ctype.h>
35#endif
36
37#if defined(WIN32) && !defined(__CYGWIN__)
38#include <windows.h>
39#ifndef INVALID_FILE_ATTRIBUTES
40#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
41#endif
42#endif
43
44#ifndef HAVE_STAT
45# ifdef HAVE__STAT
46 /* MS C library seems to define stat and _stat. The definition
47 * is identical. Still, mapping them to each other causes a warning. */
48# ifndef _MSC_VER
49# define stat(x,y) _stat(x,y)
50# endif
51# define HAVE_STAT
52# endif
53#endif
54
55#include <libxml/xmlmemory.h>
56#include <libxml/tree.h>
57#include <libxml/uri.h>
58#include "xslt.h"
59#include "xsltInternals.h"
60#include "xsltutils.h"
61#include "security.h"
62
63
64struct _xsltSecurityPrefs {
65 xsltSecurityCheck readFile;
66 xsltSecurityCheck createFile;
67 xsltSecurityCheck createDir;
68 xsltSecurityCheck readNet;
69 xsltSecurityCheck writeNet;
70};
71
72static xsltSecurityPrefsPtr xsltDefaultSecurityPrefs = NULL;
73
74/************************************************************************
75 * *
76 * Module interfaces *
77 * *
78 ************************************************************************/
79
80/**
81 * xsltNewSecurityPrefs:
82 *
83 * Create a new security preference block
84 *
85 * Returns a pointer to the new block or NULL in case of error
86 */
87xsltSecurityPrefsPtr
88xsltNewSecurityPrefs(void) {
89 xsltSecurityPrefsPtr ret;
90
91 ret = (xsltSecurityPrefsPtr) xmlMalloc(sizeof(xsltSecurityPrefs));
92 if (ret == NULL) {
93 xsltTransformError(NULL, NULL, NULL,
94 "xsltNewSecurityPrefs : malloc failed\n");
95 return(NULL);
96 }
97 memset(ret, 0, sizeof(xsltSecurityPrefs));
98 return(ret);
99}
100
101/**
102 * xsltFreeSecurityPrefs:
103 * @sec: the security block to free
104 *
105 * Free up a security preference block
106 */
107void
108xsltFreeSecurityPrefs(xsltSecurityPrefsPtr sec) {
109 if (sec == NULL)
110 return;
111 xmlFree(sec);
112}
113
114/**
115 * xsltSetSecurityPrefs:
116 * @sec: the security block to update
117 * @option: the option to update
118 * @func: the user callback to use for this option
119 *
120 * Update the security option to use the new callback checking function
121 *
122 * Returns -1 in case of error, 0 otherwise
123 */
124int
125xsltSetSecurityPrefs(xsltSecurityPrefsPtr sec, xsltSecurityOption option,
126 xsltSecurityCheck func) {
127 if (sec == NULL)
128 return(-1);
129 switch (option) {
130 case XSLT_SECPREF_READ_FILE:
131 sec->readFile = func; return(0);
132 case XSLT_SECPREF_WRITE_FILE:
133 sec->createFile = func; return(0);
134 case XSLT_SECPREF_CREATE_DIRECTORY:
135 sec->createDir = func; return(0);
136 case XSLT_SECPREF_READ_NETWORK:
137 sec->readNet = func; return(0);
138 case XSLT_SECPREF_WRITE_NETWORK:
139 sec->writeNet = func; return(0);
140 }
141 return(-1);
142}
143
144/**
145 * xsltGetSecurityPrefs:
146 * @sec: the security block to update
147 * @option: the option to lookup
148 *
149 * Lookup the security option to get the callback checking function
150 *
151 * Returns NULL if not found, the function otherwise
152 */
153xsltSecurityCheck
154xsltGetSecurityPrefs(xsltSecurityPrefsPtr sec, xsltSecurityOption option) {
155 if (sec == NULL)
156 return(NULL);
157 switch (option) {
158 case XSLT_SECPREF_READ_FILE:
159 return(sec->readFile);
160 case XSLT_SECPREF_WRITE_FILE:
161 return(sec->createFile);
162 case XSLT_SECPREF_CREATE_DIRECTORY:
163 return(sec->createDir);
164 case XSLT_SECPREF_READ_NETWORK:
165 return(sec->readNet);
166 case XSLT_SECPREF_WRITE_NETWORK:
167 return(sec->writeNet);
168 }
169 return(NULL);
170}
171
172/**
173 * xsltSetDefaultSecurityPrefs:
174 * @sec: the security block to use
175 *
176 * Set the default security preference application-wide
177 */
178void
179xsltSetDefaultSecurityPrefs(xsltSecurityPrefsPtr sec) {
180 xsltDefaultSecurityPrefs = sec;
181}
182
183/**
184 * xsltGetDefaultSecurityPrefs:
185 *
186 * Get the default security preference application-wide
187 *
188 * Returns the current xsltSecurityPrefsPtr in use or NULL if none
189 */
190xsltSecurityPrefsPtr
191xsltGetDefaultSecurityPrefs(void) {
192 return(xsltDefaultSecurityPrefs);
193}
194
195/**
196 * xsltSetCtxtSecurityPrefs:
197 * @sec: the security block to use
198 * @ctxt: an XSLT transformation context
199 *
200 * Set the security preference for a specific transformation
201 *
202 * Returns -1 in case of error, 0 otherwise
203 */
204int
205xsltSetCtxtSecurityPrefs(xsltSecurityPrefsPtr sec,
206 xsltTransformContextPtr ctxt) {
207 if (ctxt == NULL)
208 return(-1);
209 ctxt->sec = (void *) sec;
210 return(0);
211}
212
213
214/**
215 * xsltSecurityAllow:
216 * @sec: the security block to use
217 * @ctxt: an XSLT transformation context
218 * @value: unused
219 *
220 * Function used to always allow an operation
221 *
222 * Returns 1 always
223 */
224int
225xsltSecurityAllow(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED,
226 xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
227 const char *value ATTRIBUTE_UNUSED) {
228 return(1);
229}
230
231/**
232 * xsltSecurityForbid:
233 * @sec: the security block to use
234 * @ctxt: an XSLT transformation context
235 * @value: unused
236 *
237 * Function used to always forbid an operation
238 *
239 * Returns 0 always
240 */
241int
242xsltSecurityForbid(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED,
243 xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
244 const char *value ATTRIBUTE_UNUSED) {
245 return(0);
246}
247
248/************************************************************************
249 * *
250 * Internal interfaces *
251 * *
252 ************************************************************************/
253
254/**
255 * xsltCheckFilename
256 * @path: the path to check
257 *
258 * function checks to see if @path is a valid source
259 * (file, socket...) for XML.
260 *
261 * TODO: remove at some point !!!
262 * Local copy of xmlCheckFilename to avoid a hard dependency on
263 * a new version of libxml2
264 *
265 * if stat is not available on the target machine,
266 * returns 1. if stat fails, returns 0 (if calling
267 * stat on the filename fails, it can't be right).
268 * if stat succeeds and the file is a directory,
269 * returns 2. otherwise returns 1.
270 */
271
272static int
273xsltCheckFilename (const char *path)
274{
275#ifdef HAVE_STAT
276 struct stat stat_buffer;
277#if defined(WIN32) && !defined(__CYGWIN__)
278 DWORD dwAttrs;
279
280 dwAttrs = GetFileAttributes(path);
281 if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
282 if (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) {
283 return 2;
284 }
285 }
286#endif
287
288 if (stat(path, &stat_buffer) == -1)
289 return 0;
290
291#ifdef S_ISDIR
292 if (S_ISDIR(stat_buffer.st_mode)) {
293 return 2;
294 }
295#endif
296#endif
297 return 1;
298}
299
300static int
301xsltCheckWritePath(xsltSecurityPrefsPtr sec,
302 xsltTransformContextPtr ctxt,
303 const char *path)
304{
305 int ret;
306 xsltSecurityCheck check;
307 char *directory;
308
309 check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE);
310 if (check != NULL) {
311 ret = check(sec, ctxt, path);
312 if (ret == 0) {
313 xsltTransformError(ctxt, NULL, NULL,
314 "File write for %s refused\n", path);
315 return(0);
316 }
317 }
318
319 directory = xmlParserGetDirectory (path);
320
321 if (directory != NULL) {
322 ret = xsltCheckFilename(directory);
323 if (ret == 0) {
324 /*
325 * The directory doesn't exist check for creation
326 */
327 check = xsltGetSecurityPrefs(sec,
328 XSLT_SECPREF_CREATE_DIRECTORY);
329 if (check != NULL) {
330 ret = check(sec, ctxt, directory);
331 if (ret == 0) {
332 xsltTransformError(ctxt, NULL, NULL,
333 "Directory creation for %s refused\n",
334 path);
335 xmlFree(directory);
336 return(0);
337 }
338 }
339 ret = xsltCheckWritePath(sec, ctxt, directory);
340 if (ret == 1)
341 ret = mkdir(directory, 0755);
342 }
343 xmlFree(directory);
344 if (ret < 0)
345 return(ret);
346 }
347
348 return(1);
349}
350
351/**
352 * xsltCheckWrite:
353 * @sec: the security options
354 * @ctxt: an XSLT transformation context
355 * @URL: the resource to be written
356 *
357 * Check if the resource is allowed to be written, if necessary makes
358 * some preliminary work like creating directories
359 *
360 * Return 1 if write is allowed, 0 if not and -1 in case or error.
361 */
362int
363xsltCheckWrite(xsltSecurityPrefsPtr sec,
364 xsltTransformContextPtr ctxt, const xmlChar *URL) {
365 int ret;
366 xmlURIPtr uri;
367 xsltSecurityCheck check;
368
369 uri = xmlParseURI((const char *)URL);
370 if (uri == NULL) {
371 uri = xmlCreateURI();
372 if (uri == NULL) {
373 xsltTransformError(ctxt, NULL, NULL,
374 "xsltCheckWrite: out of memory for %s\n", URL);
375 return(-1);
376 }
377 uri->path = (char *)xmlStrdup(URL);
378 }
379 if ((uri->scheme == NULL) ||
380 (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
381
382#if defined(WIN32) && !defined(__CYGWIN__)
383 if ((uri->path)&&(uri->path[0]=='/')&&
384 (uri->path[1]!='\0')&&(uri->path[2]==':'))
385 ret = xsltCheckWritePath(sec, ctxt, uri->path+1);
386 else
387#endif
388
389 /*
390 * Check if we are allowed to write this file
391 */
392 ret = xsltCheckWritePath(sec, ctxt, uri->path);
393 if (ret <= 0) {
394 xmlFreeURI(uri);
395 return(ret);
396 }
397 } else {
398 /*
399 * Check if we are allowed to write this network resource
400 */
401 check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_WRITE_NETWORK);
402 if (check != NULL) {
403 ret = check(sec, ctxt, (const char *)URL);
404 if (ret == 0) {
405 xsltTransformError(ctxt, NULL, NULL,
406 "File write for %s refused\n", URL);
407 xmlFreeURI(uri);
408 return(0);
409 }
410 }
411 }
412 xmlFreeURI(uri);
413 return(1);
414}
415
416
417/**
418 * xsltCheckRead:
419 * @sec: the security options
420 * @ctxt: an XSLT transformation context
421 * @URL: the resource to be read
422 *
423 * Check if the resource is allowed to be read
424 *
425 * Return 1 if read is allowed, 0 if not and -1 in case or error.
426 */
427int
428xsltCheckRead(xsltSecurityPrefsPtr sec,
429 xsltTransformContextPtr ctxt, const xmlChar *URL) {
430 int ret;
431 xmlURIPtr uri;
432 xsltSecurityCheck check;
433
434 uri = xmlParseURI((const char *)URL);
435 if (uri == NULL) {
436 xsltTransformError(ctxt, NULL, NULL,
437 "xsltCheckRead: URL parsing failed for %s\n",
438 URL);
439 return(-1);
440 }
441 if ((uri->scheme == NULL) ||
442 (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
443
444 /*
445 * Check if we are allowed to read this file
446 */
447 check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_READ_FILE);
448 if (check != NULL) {
449 ret = check(sec, ctxt, uri->path);
450 if (ret == 0) {
451 xsltTransformError(ctxt, NULL, NULL,
452 "Local file read for %s refused\n", URL);
453 xmlFreeURI(uri);
454 return(0);
455 }
456 }
457 } else {
458 /*
459 * Check if we are allowed to write this network resource
460 */
461 check = xsltGetSecurityPrefs(sec, XSLT_SECPREF_READ_NETWORK);
462 if (check != NULL) {
463 ret = check(sec, ctxt, (const char *)URL);
464 if (ret == 0) {
465 xsltTransformError(ctxt, NULL, NULL,
466 "Network file read for %s refused\n", URL);
467 xmlFreeURI(uri);
468 return(0);
469 }
470 }
471 }
472 xmlFreeURI(uri);
473 return(1);
474}
475
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette