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