blob: 996296273e40924bb23cff3ac394a3ec5ba0d6aa [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% PPPP OOO L IIIII CCCC Y Y %
6% P P O O L I C Y Y %
7% PPPP O O L I C Y %
8% P O O L I C Y %
9% P OOO LLLLL IIIII CCCC Y %
10% %
11% %
12% MagickCore Policy Methods %
13% %
14% Software Design %
15% John Cristy %
16% July 1992 %
17% %
18% %
cristy1454be72011-12-19 01:52:48 +000019% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000020% dedicated to making software imaging solutions freely available. %
21% %
22% You may not use this file except in compliance with the License. You may %
23% obtain a copy of the License at %
24% %
25% http://www.imagemagick.org/script/license.php %
26% %
27% Unless required by applicable law or agreed to in writing, software %
28% distributed under the License is distributed on an "AS IS" BASIS, %
29% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30% See the License for the specific language governing permissions and %
31% limitations under the License. %
32% %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35% We use linked-lists because splay-trees do not currently support duplicate
36% key / value pairs (.e.g X11 green compliance and SVG green compliance).
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
44#include "MagickCore/client.h"
45#include "MagickCore/configure.h"
cristy9639ba32011-09-05 15:09:42 +000046#include "MagickCore/configure-private.h"
cristy4c08aed2011-07-01 19:47:50 +000047#include "MagickCore/exception.h"
48#include "MagickCore/exception-private.h"
49#include "MagickCore/memory_.h"
50#include "MagickCore/monitor.h"
51#include "MagickCore/monitor-private.h"
52#include "MagickCore/option.h"
53#include "MagickCore/policy.h"
cristy5ff4eaf2011-09-03 01:38:02 +000054#include "MagickCore/policy-private.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/semaphore.h"
56#include "MagickCore/string_.h"
57#include "MagickCore/token.h"
58#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000059#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000060#include "MagickCore/xml-tree.h"
cristy3ed852e2009-09-05 21:47:34 +000061
62/*
63 Define declarations.
64*/
65#define PolicyFilename "policy.xml"
66
67/*
cristy54a531d2009-10-21 17:58:01 +000068 Typedef declarations.
cristy3ed852e2009-09-05 21:47:34 +000069*/
70struct _PolicyInfo
71{
72 char
cristy54a531d2009-10-21 17:58:01 +000073 *path;
cristy3ed852e2009-09-05 21:47:34 +000074
75 PolicyDomain
76 domain;
77
78 PolicyRights
79 rights;
80
81 char
cristy54a531d2009-10-21 17:58:01 +000082 *name,
cristy3ed852e2009-09-05 21:47:34 +000083 *pattern,
84 *value;
85
86 MagickBooleanType
cristy54a531d2009-10-21 17:58:01 +000087 exempt,
cristy3ed852e2009-09-05 21:47:34 +000088 stealth,
89 debug;
90
91 SemaphoreInfo
92 *semaphore;
93
cristybb503372010-05-27 20:51:26 +000094 size_t
cristy3ed852e2009-09-05 21:47:34 +000095 signature;
96};
cristy54a531d2009-10-21 17:58:01 +000097
98typedef struct _PolicyMapInfo
99{
100 const PolicyDomain
101 domain;
102
103 const PolicyRights
104 rights;
105
106 const char
107 *name,
108 *pattern,
109 *value;
110} PolicyMapInfo;
cristy3ed852e2009-09-05 21:47:34 +0000111
112/*
113 Static declarations.
114*/
cristy54a531d2009-10-21 17:58:01 +0000115static const PolicyMapInfo
116 PolicyMap[] =
117 {
cristyfa378d92009-10-23 15:41:15 +0000118 { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
119 (const char *) NULL, (const char *) NULL }
cristy54a531d2009-10-21 17:58:01 +0000120 };
121
cristy3ed852e2009-09-05 21:47:34 +0000122static LinkedListInfo
123 *policy_list = (LinkedListInfo *) NULL;
124
125static SemaphoreInfo
126 *policy_semaphore = (SemaphoreInfo *) NULL;
127
128static volatile MagickBooleanType
129 instantiate_policy = MagickFalse;
130
131/*
132 Forward declarations.
133*/
134static MagickBooleanType
135 InitializePolicyList(ExceptionInfo *),
136 LoadPolicyLists(const char *,ExceptionInfo *);
137
138/*
139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140% %
141% %
142% %
cristy3ed852e2009-09-05 21:47:34 +0000143+ G e t P o l i c y I n f o %
144% %
145% %
146% %
147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148%
149% GetPolicyInfo() searches the policy list for the specified name and if found
150% returns attributes for that policy.
151%
152% The format of the GetPolicyInfo method is:
153%
154% PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
155%
156% A description of each parameter follows:
157%
158% o name: the policy name.
159%
160% o exception: return any errors or warnings in this structure.
161%
162*/
163static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
164{
165 char
166 policyname[MaxTextExtent];
167
168 register PolicyInfo
169 *p;
170
171 register char
172 *q;
173
174 assert(exception != (ExceptionInfo *) NULL);
175 if ((policy_list == (LinkedListInfo *) NULL) ||
176 (instantiate_policy == MagickFalse))
177 if (InitializePolicyList(exception) == MagickFalse)
178 return((PolicyInfo *) NULL);
179 if ((policy_list == (LinkedListInfo *) NULL) ||
180 (IsLinkedListEmpty(policy_list) != MagickFalse))
181 return((PolicyInfo *) NULL);
182 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
183 return((PolicyInfo *) GetValueFromLinkedList(policy_list,0));
184 /*
185 Strip names of whitespace.
186 */
187 (void) CopyMagickString(policyname,name,MaxTextExtent);
188 for (q=policyname; *q != '\0'; q++)
189 {
190 if (isspace((int) ((unsigned char) *q)) == 0)
191 continue;
192 (void) CopyMagickString(q,q+1,MaxTextExtent);
193 q--;
194 }
195 /*
196 Search for policy tag.
197 */
cristyf84a1932010-01-03 18:00:18 +0000198 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000199 ResetLinkedListIterator(policy_list);
200 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
201 while (p != (PolicyInfo *) NULL)
202 {
203 if (LocaleCompare(policyname,p->name) == 0)
204 break;
205 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
206 }
cristy6446d622009-11-02 01:17:45 +0000207 if (p != (PolicyInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000208 (void) InsertValueInLinkedList(policy_list,0,
209 RemoveElementByValueFromLinkedList(policy_list,p));
cristyf84a1932010-01-03 18:00:18 +0000210 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000211 return(p);
212}
213
214/*
215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216% %
217% %
218% %
219% G e t P o l i c y I n f o L i s t %
220% %
221% %
222% %
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224%
225% GetPolicyInfoList() returns any policies that match the specified pattern.
226%
227% The format of the GetPolicyInfoList function is:
228%
229% const PolicyInfo **GetPolicyInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000230% size_t *number_policies,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000231%
232% A description of each parameter follows:
233%
234% o pattern: Specifies a pointer to a text string containing a pattern.
235%
236% o number_policies: returns the number of policies in the list.
237%
238% o exception: return any errors or warnings in this structure.
239%
240*/
241MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000242 size_t *number_policies,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000243{
244 const PolicyInfo
245 **policies;
246
247 register const PolicyInfo
248 *p;
249
cristybb503372010-05-27 20:51:26 +0000250 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000251 i;
252
253 /*
254 Allocate policy list.
255 */
256 assert(pattern != (char *) NULL);
257 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000258 assert(number_policies != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000259 *number_policies=0;
260 p=GetPolicyInfo("*",exception);
261 if (p == (const PolicyInfo *) NULL)
262 return((const PolicyInfo **) NULL);
263 policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
264 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
265 if (policies == (const PolicyInfo **) NULL)
266 return((const PolicyInfo **) NULL);
267 /*
268 Generate policy list.
269 */
cristyf84a1932010-01-03 18:00:18 +0000270 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000271 ResetLinkedListIterator(policy_list);
272 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
273 for (i=0; p != (const PolicyInfo *) NULL; )
274 {
275 if ((p->stealth == MagickFalse) &&
276 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
277 policies[i++]=p;
278 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
279 }
cristyf84a1932010-01-03 18:00:18 +0000280 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000281 policies[i]=(PolicyInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000282 *number_policies=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000283 return(policies);
284}
285
286/*
287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288% %
289% %
290% %
291% G e t P o l i c y L i s t %
292% %
293% %
294% %
295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296%
297% GetPolicyList() returns any policies that match the specified pattern.
298%
299% The format of the GetPolicyList function is:
300%
cristybb503372010-05-27 20:51:26 +0000301% char **GetPolicyList(const char *pattern,size_t *number_policies,
cristy3ed852e2009-09-05 21:47:34 +0000302% ExceptionInfo *exception)
303%
304% A description of each parameter follows:
305%
306% o pattern: a pointer to a text string containing a pattern.
307%
308% o number_policies: returns the number of policies in the list.
309%
310% o exception: return any errors or warnings in this structure.
311%
312*/
313MagickExport char **GetPolicyList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000314 size_t *number_policies,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000315{
316 char
317 **policies;
318
319 register const PolicyInfo
320 *p;
321
cristybb503372010-05-27 20:51:26 +0000322 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000323 i;
324
325 /*
326 Allocate policy list.
327 */
328 assert(pattern != (char *) NULL);
329 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000330 assert(number_policies != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000331 *number_policies=0;
332 p=GetPolicyInfo("*",exception);
333 if (p == (const PolicyInfo *) NULL)
334 return((char **) NULL);
335 policies=(char **) AcquireQuantumMemory((size_t)
336 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
337 if (policies == (char **) NULL)
338 return((char **) NULL);
339 /*
340 Generate policy list.
341 */
cristyf84a1932010-01-03 18:00:18 +0000342 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000343 ResetLinkedListIterator(policy_list);
344 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
345 for (i=0; p != (const PolicyInfo *) NULL; )
346 {
347 if ((p->stealth == MagickFalse) &&
348 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
349 policies[i++]=ConstantString(p->name);
350 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
351 }
cristyf84a1932010-01-03 18:00:18 +0000352 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000353 policies[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000354 *number_policies=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000355 return(policies);
356}
357
358/*
359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360% %
361% %
362% %
363% G e t P o l i c y V a l u e %
364% %
365% %
366% %
367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
368%
369% GetPolicyValue() returns the value associated with the named policy.
370%
371% The format of the GetPolicyValue method is:
372%
373% char *GetPolicyValue(const char *name)
374%
375% A description of each parameter follows:
376%
377% o policy_info: The policy info.
378%
379*/
380MagickExport char *GetPolicyValue(const char *name)
381{
382 const char
383 *value;
384
385 const PolicyInfo
386 *policy_info;
387
388 ExceptionInfo
389 *exception;
390
391 assert(name != (const char *) NULL);
392 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
393 exception=AcquireExceptionInfo();
394 policy_info=GetPolicyInfo(name,exception);
395 exception=DestroyExceptionInfo(exception);
396 if (policy_info == (PolicyInfo *) NULL)
397 return((char *) NULL);
398 value=policy_info->value;
399 if ((value == (const char *) NULL) || (*value == '\0'))
400 return((char *) NULL);
401 return(ConstantString(value));
402}
403
404/*
405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406% %
407% %
408% %
409+ I n i t i a l i z e P o l i c y L i s t %
410% %
411% %
412% %
413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414%
415% InitializePolicyList() initializes the policy list.
416%
417% The format of the InitializePolicyList method is:
418%
419% MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
420%
421% A description of each parameter follows.
422%
423% o exception: return any errors or warnings in this structure.
424%
425*/
426static MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
427{
428 if ((policy_list == (LinkedListInfo *) NULL) &&
429 (instantiate_policy == MagickFalse))
430 {
cristy4e1dff62009-10-25 20:36:03 +0000431 if (policy_semaphore == (SemaphoreInfo *) NULL)
432 AcquireSemaphoreInfo(&policy_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000433 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000434 if ((policy_list == (LinkedListInfo *) NULL) &&
435 (instantiate_policy == MagickFalse))
436 {
437 (void) LoadPolicyLists(PolicyFilename,exception);
438 instantiate_policy=MagickTrue;
439 }
cristyf84a1932010-01-03 18:00:18 +0000440 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000441 }
442 return(policy_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
443}
444
445/*
446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447% %
448% %
449% %
cristy3ed852e2009-09-05 21:47:34 +0000450% I s R i g h t s A u t h o r i z e d %
451% %
452% %
453% %
454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
455%
456% IsRightsAuthorized() returns MagickTrue if the policy authorizes the
457% requested rights for the specified domain.
458%
459% The format of the IsRightsAuthorized method is:
460%
461% MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
462% const PolicyRights rights,const char *pattern)
463%
464% A description of each parameter follows:
465%
466% o domain: the policy domain.
467%
468% o rights: the policy rights.
469%
470% o pattern: the coder, delegate, filter, or path pattern.
471%
472*/
473MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
474 const PolicyRights rights,const char *pattern)
475{
476 const PolicyInfo
477 *policy_info;
478
479 ExceptionInfo
480 *exception;
481
482 MagickBooleanType
483 authorized;
484
485 register PolicyInfo
486 *p;
487
488 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
489 "Domain: %s; rights=%s; pattern=\"%s\" ...",
cristy042ee782011-04-22 18:48:30 +0000490 CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
491 CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
cristy3ed852e2009-09-05 21:47:34 +0000492 exception=AcquireExceptionInfo();
493 policy_info=GetPolicyInfo("*",exception);
494 exception=DestroyExceptionInfo(exception);
495 if (policy_info == (PolicyInfo *) NULL)
496 return(MagickTrue);
497 authorized=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000498 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000499 ResetLinkedListIterator(policy_list);
500 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
501 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
502 {
503 if ((p->domain == domain) &&
504 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
505 {
506 if (((rights & ReadPolicyRights) != 0) &&
507 ((p->rights & ReadPolicyRights) == 0))
508 authorized=MagickFalse;
509 if (((rights & WritePolicyRights) != 0) &&
510 ((p->rights & WritePolicyRights) == 0))
511 authorized=MagickFalse;
512 if (((rights & ExecutePolicyRights) != 0) &&
513 ((p->rights & ExecutePolicyRights) == 0))
514 authorized=MagickFalse;
515 }
516 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
517 }
cristyf84a1932010-01-03 18:00:18 +0000518 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000519 return(authorized);
520}
521
522/*
523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524% %
525% %
526% %
527% L i s t P o l i c y I n f o %
528% %
529% %
530% %
531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532%
533% ListPolicyInfo() lists policies to the specified file.
534%
535% The format of the ListPolicyInfo method is:
536%
537% MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
538%
539% A description of each parameter follows.
540%
541% o file: List policy names to this file handle.
542%
543% o exception: return any errors or warnings in this structure.
544%
545*/
546MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
547 ExceptionInfo *exception)
548{
549 const char
550 *path,
551 *domain;
552
553 const PolicyInfo
554 **policy_info;
555
cristybb503372010-05-27 20:51:26 +0000556 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000557 i;
558
cristybb503372010-05-27 20:51:26 +0000559 size_t
cristy3ed852e2009-09-05 21:47:34 +0000560 number_policies;
561
562 /*
563 List name and attributes of each policy in the list.
564 */
565 if (file == (const FILE *) NULL)
566 file=stdout;
567 policy_info=GetPolicyInfoList("*",&number_policies,exception);
568 if (policy_info == (const PolicyInfo **) NULL)
569 return(MagickFalse);
570 path=(const char *) NULL;
cristybb503372010-05-27 20:51:26 +0000571 for (i=0; i < (ssize_t) number_policies; i++)
cristy3ed852e2009-09-05 21:47:34 +0000572 {
573 if (policy_info[i]->stealth != MagickFalse)
574 continue;
575 if (((path == (const char *) NULL) ||
576 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
577 (policy_info[i]->path != (char *) NULL))
cristyb51dff52011-05-19 16:55:47 +0000578 (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
cristy3ed852e2009-09-05 21:47:34 +0000579 path=policy_info[i]->path;
cristy042ee782011-04-22 18:48:30 +0000580 domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
cristy3ed852e2009-09-05 21:47:34 +0000581 policy_info[i]->domain);
cristyb51dff52011-05-19 16:55:47 +0000582 (void) FormatLocaleFile(file," Policy: %s\n",domain);
cristy7ce14bc2010-01-17 00:01:01 +0000583 if ((policy_info[i]->domain == ResourcePolicyDomain) ||
584 (policy_info[i]->domain == SystemPolicyDomain))
cristy3ed852e2009-09-05 21:47:34 +0000585 {
586 if (policy_info[i]->name != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000587 (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
cristy3ed852e2009-09-05 21:47:34 +0000588 if (policy_info[i]->value != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000589 (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
cristy3ed852e2009-09-05 21:47:34 +0000590 }
591 else
592 {
cristyb51dff52011-05-19 16:55:47 +0000593 (void) FormatLocaleFile(file," rights: ");
cristy3ed852e2009-09-05 21:47:34 +0000594 if (policy_info[i]->rights == NoPolicyRights)
cristyb51dff52011-05-19 16:55:47 +0000595 (void) FormatLocaleFile(file,"None ");
cristy3ed852e2009-09-05 21:47:34 +0000596 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
cristyb51dff52011-05-19 16:55:47 +0000597 (void) FormatLocaleFile(file,"Read ");
cristy3ed852e2009-09-05 21:47:34 +0000598 if ((policy_info[i]->rights & WritePolicyRights) != 0)
cristyb51dff52011-05-19 16:55:47 +0000599 (void) FormatLocaleFile(file,"Write ");
cristy3ed852e2009-09-05 21:47:34 +0000600 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
cristyb51dff52011-05-19 16:55:47 +0000601 (void) FormatLocaleFile(file,"Execute ");
602 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +0000603 if (policy_info[i]->pattern != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +0000604 (void) FormatLocaleFile(file," pattern: %s\n",
605 policy_info[i]->pattern);
cristy3ed852e2009-09-05 21:47:34 +0000606 }
607 }
608 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
609 policy_info);
610 (void) fflush(file);
611 return(MagickTrue);
612}
613
614/*
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616% %
617% %
618% %
619+ L o a d P o l i c y L i s t %
620% %
621% %
622% %
623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624%
625% LoadPolicyList() loads the policy configuration file which provides a mapping
626% between policy attributes and a policy domain.
627%
628% The format of the LoadPolicyList method is:
629%
630% MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000631% const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000632%
633% A description of each parameter follows:
634%
635% o xml: The policy list in XML format.
636%
637% o filename: The policy list filename.
638%
639% o depth: depth of <include /> statements.
640%
641% o exception: return any errors or warnings in this structure.
642%
643*/
644static MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000645 const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000646{
647 char
648 keyword[MaxTextExtent],
649 *token;
650
651 PolicyInfo
652 *policy_info;
653
654 const char
655 *q;
656
657 MagickBooleanType
658 status;
659
660 /*
661 Load the policy map file.
662 */
663 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
664 "Loading policy file \"%s\" ...",filename);
665 if (xml == (char *) NULL)
666 return(MagickFalse);
667 if (policy_list == (LinkedListInfo *) NULL)
668 {
669 policy_list=NewLinkedList(0);
670 if (policy_list == (LinkedListInfo *) NULL)
671 {
672 ThrowFileException(exception,ResourceLimitError,
673 "MemoryAllocationFailed",filename);
674 return(MagickFalse);
675 }
676 }
677 status=MagickTrue;
678 policy_info=(PolicyInfo *) NULL;
679 token=AcquireString(xml);
680 for (q=(const char *) xml; *q != '\0'; )
681 {
682 /*
683 Interpret XML.
684 */
685 GetMagickToken(q,&q,token);
686 if (*token == '\0')
687 break;
688 (void) CopyMagickString(keyword,token,MaxTextExtent);
689 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
690 {
691 /*
692 Docdomain element.
693 */
694 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
695 GetMagickToken(q,&q,token);
696 continue;
697 }
698 if (LocaleNCompare(keyword,"<!--",4) == 0)
699 {
700 /*
701 Comment element.
702 */
703 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
704 GetMagickToken(q,&q,token);
705 continue;
706 }
707 if (LocaleCompare(keyword,"<include") == 0)
708 {
709 /*
710 Include element.
711 */
712 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
713 {
714 (void) CopyMagickString(keyword,token,MaxTextExtent);
715 GetMagickToken(q,&q,token);
716 if (*token != '=')
717 continue;
718 GetMagickToken(q,&q,token);
719 if (LocaleCompare(keyword,"file") == 0)
720 {
721 if (depth > 200)
722 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000723 ConfigureError,"IncludeElementNestedTooDeeply","'%s'",token);
cristy3ed852e2009-09-05 21:47:34 +0000724 else
725 {
726 char
727 path[MaxTextExtent],
728 *xml;
729
730 GetPathComponent(filename,HeadPath,path);
731 if (*path != '\0')
732 (void) ConcatenateMagickString(path,DirectorySeparator,
733 MaxTextExtent);
734 if (*token == *DirectorySeparator)
735 (void) CopyMagickString(path,token,MaxTextExtent);
736 else
737 (void) ConcatenateMagickString(path,token,MaxTextExtent);
738 xml=FileToString(path,~0,exception);
739 if (xml != (char *) NULL)
740 {
741 status=LoadPolicyList(xml,path,depth+1,exception);
742 xml=(char *) RelinquishMagickMemory(xml);
743 }
744 }
745 }
746 }
747 continue;
748 }
749 if (LocaleCompare(keyword,"<policy") == 0)
750 {
751 /*
752 Policy element.
753 */
cristy73bd4a52010-10-05 11:24:23 +0000754 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
cristy3ed852e2009-09-05 21:47:34 +0000755 if (policy_info == (PolicyInfo *) NULL)
756 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
757 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
758 policy_info->path=ConstantString(filename);
cristy54a531d2009-10-21 17:58:01 +0000759 policy_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000760 policy_info->signature=MagickSignature;
761 continue;
762 }
763 if (policy_info == (PolicyInfo *) NULL)
764 continue;
765 if (LocaleCompare(keyword,"/>") == 0)
766 {
767 status=AppendValueToLinkedList(policy_list,policy_info);
768 if (status == MagickFalse)
769 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000770 ResourceLimitError,"MemoryAllocationFailed","'%s'",
cristy3ed852e2009-09-05 21:47:34 +0000771 policy_info->name);
772 policy_info=(PolicyInfo *) NULL;
773 }
774 GetMagickToken(q,(const char **) NULL,token);
775 if (*token != '=')
776 continue;
777 GetMagickToken(q,&q,token);
778 GetMagickToken(q,&q,token);
779 switch (*keyword)
780 {
781 case 'D':
782 case 'd':
783 {
784 if (LocaleCompare((char *) keyword,"domain") == 0)
785 {
cristy042ee782011-04-22 18:48:30 +0000786 policy_info->domain=(PolicyDomain) ParseCommandOption(
cristy3ed852e2009-09-05 21:47:34 +0000787 MagickPolicyDomainOptions,MagickTrue,token);
788 break;
789 }
790 break;
791 }
792 case 'N':
793 case 'n':
794 {
795 if (LocaleCompare((char *) keyword,"name") == 0)
796 {
797 policy_info->name=ConstantString(token);
798 break;
799 }
800 break;
801 }
802 case 'P':
803 case 'p':
804 {
805 if (LocaleCompare((char *) keyword,"pattern") == 0)
806 {
807 policy_info->pattern=ConstantString(token);
808 break;
809 }
810 break;
811 }
812 case 'R':
813 case 'r':
814 {
815 if (LocaleCompare((char *) keyword,"rights") == 0)
816 {
cristy042ee782011-04-22 18:48:30 +0000817 policy_info->rights=(PolicyRights) ParseCommandOption(
cristy3ed852e2009-09-05 21:47:34 +0000818 MagickPolicyRightsOptions,MagickTrue,token);
819 break;
820 }
821 break;
822 }
823 case 'S':
824 case 's':
825 {
826 if (LocaleCompare((char *) keyword,"stealth") == 0)
827 {
anthony6f201312012-03-30 04:08:15 +0000828 policy_info->stealth=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +0000829 break;
830 }
831 break;
832 }
833 case 'V':
834 case 'v':
835 {
836 if (LocaleCompare((char *) keyword,"value") == 0)
837 {
838 policy_info->value=ConstantString(token);
839 break;
840 }
841 break;
842 }
843 default:
844 break;
845 }
846 }
847 token=(char *) RelinquishMagickMemory(token);
848 return(status);
849}
850
851/*
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853% %
854% %
855% %
856% L o a d P o l i c y L i s t s %
857% %
858% %
859% %
860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861%
862% LoadPolicyList() loads one or more policy configuration file which provides a
863% mapping between policy attributes and a policy name.
864%
865% The format of the LoadPolicyLists method is:
866%
867% MagickBooleanType LoadPolicyLists(const char *filename,
868% ExceptionInfo *exception)
869%
870% A description of each parameter follows:
871%
872% o filename: the font file name.
873%
874% o exception: return any errors or warnings in this structure.
875%
876*/
877static MagickBooleanType LoadPolicyLists(const char *filename,
878 ExceptionInfo *exception)
879{
cristy3ed852e2009-09-05 21:47:34 +0000880 const StringInfo
881 *option;
882
883 LinkedListInfo
884 *options;
885
886 MagickStatusType
887 status;
888
cristybb503372010-05-27 20:51:26 +0000889 register ssize_t
cristy54a531d2009-10-21 17:58:01 +0000890 i;
891
892 /*
893 Load built-in policy map.
894 */
cristy3ed852e2009-09-05 21:47:34 +0000895 status=MagickFalse;
cristy54a531d2009-10-21 17:58:01 +0000896 if (policy_list == (LinkedListInfo *) NULL)
897 {
898 policy_list=NewLinkedList(0);
899 if (policy_list == (LinkedListInfo *) NULL)
900 {
901 ThrowFileException(exception,ResourceLimitError,
902 "MemoryAllocationFailed",filename);
903 return(MagickFalse);
904 }
905 }
cristybb503372010-05-27 20:51:26 +0000906 for (i=0; i < (ssize_t) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
cristy54a531d2009-10-21 17:58:01 +0000907 {
908 PolicyInfo
909 *policy_info;
910
911 register const PolicyMapInfo
912 *p;
913
914 p=PolicyMap+i;
cristy73bd4a52010-10-05 11:24:23 +0000915 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
cristy54a531d2009-10-21 17:58:01 +0000916 if (policy_info == (PolicyInfo *) NULL)
917 {
918 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000919 ResourceLimitError,"MemoryAllocationFailed","'%s'",policy_info->name);
cristy54a531d2009-10-21 17:58:01 +0000920 continue;
921 }
922 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
923 policy_info->path=(char *) "[built-in]";
924 policy_info->domain=p->domain;
925 policy_info->rights=p->rights;
926 policy_info->name=(char *) p->name;
927 policy_info->pattern=(char *) p->pattern;
928 policy_info->value=(char *) p->value;
929 policy_info->exempt=MagickTrue;
930 policy_info->signature=MagickSignature;
931 status=AppendValueToLinkedList(policy_list,policy_info);
932 if (status == MagickFalse)
933 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000934 ResourceLimitError,"MemoryAllocationFailed","'%s'",policy_info->name);
cristy54a531d2009-10-21 17:58:01 +0000935 }
936 /*
937 Load external policy map.
938 */
cristy3ed852e2009-09-05 21:47:34 +0000939 options=GetConfigureOptions(filename,exception);
940 option=(const StringInfo *) GetNextValueInLinkedList(options);
941 while (option != (const StringInfo *) NULL)
942 {
943 status|=LoadPolicyList((const char *) GetStringInfoDatum(option),
944 GetStringInfoPath(option),0,exception);
945 option=(const StringInfo *) GetNextValueInLinkedList(options);
946 }
947 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +0000948 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000949}
cristyf34a1452009-10-24 22:29:27 +0000950
951/*
952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953% %
954% %
955% %
956+ P o l i c y C o m p o n e n t G e n e s i s %
957% %
958% %
959% %
960%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961%
962% PolicyComponentGenesis() instantiates the policy component.
963%
964% The format of the PolicyComponentGenesis method is:
965%
966% MagickBooleanType PolicyComponentGenesis(void)
967%
968*/
cristy5ff4eaf2011-09-03 01:38:02 +0000969MagickPrivate MagickBooleanType PolicyComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000970{
cristy165b6092009-10-26 13:52:10 +0000971 AcquireSemaphoreInfo(&policy_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000972 return(MagickTrue);
973}
974
975/*
976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977% %
978% %
979% %
980+ P o l i c y C o m p o n e n t T e r m i n u s %
981% %
982% %
983% %
984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985%
986% PolicyComponentTerminus() destroys the policy component.
987%
988% The format of the PolicyComponentTerminus method is:
989%
990% PolicyComponentTerminus(void)
991%
992*/
993
994static void *DestroyPolicyElement(void *policy_info)
995{
996 register PolicyInfo
997 *p;
998
999 p=(PolicyInfo *) policy_info;
1000 if (p->exempt == MagickFalse)
1001 {
1002 if (p->value != (char *) NULL)
1003 p->value=DestroyString(p->value);
1004 if (p->pattern != (char *) NULL)
1005 p->pattern=DestroyString(p->pattern);
1006 if (p->name != (char *) NULL)
1007 p->name=DestroyString(p->name);
1008 if (p->path != (char *) NULL)
1009 p->path=DestroyString(p->path);
1010 }
1011 p=(PolicyInfo *) RelinquishMagickMemory(p);
1012 return((void *) NULL);
1013}
1014
cristy5ff4eaf2011-09-03 01:38:02 +00001015MagickPrivate void PolicyComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001016{
cristy18b17442009-10-25 18:36:48 +00001017 if (policy_semaphore == (SemaphoreInfo *) NULL)
1018 AcquireSemaphoreInfo(&policy_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001019 LockSemaphoreInfo(policy_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001020 if (policy_list != (LinkedListInfo *) NULL)
1021 policy_list=DestroyLinkedList(policy_list,DestroyPolicyElement);
1022 instantiate_policy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001023 UnlockSemaphoreInfo(policy_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001024 DestroySemaphoreInfo(&policy_semaphore);
1025}