blob: b7646bc22bb09338ec5af91f3e3aae3fde365987 [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% %
19% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
20% 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*/
43#include "magick/studio.h"
44#include "magick/client.h"
45#include "magick/configure.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/memory_.h"
49#include "magick/monitor.h"
50#include "magick/monitor-private.h"
51#include "magick/option.h"
52#include "magick/policy.h"
53#include "magick/semaphore.h"
54#include "magick/string_.h"
55#include "magick/token.h"
56#include "magick/utility.h"
57#include "magick/xml-tree.h"
58
59/*
60 Define declarations.
61*/
62#define PolicyFilename "policy.xml"
63
64/*
cristy54a531d2009-10-21 17:58:01 +000065 Typedef declarations.
cristy3ed852e2009-09-05 21:47:34 +000066*/
67struct _PolicyInfo
68{
69 char
cristy54a531d2009-10-21 17:58:01 +000070 *path;
cristy3ed852e2009-09-05 21:47:34 +000071
72 PolicyDomain
73 domain;
74
75 PolicyRights
76 rights;
77
78 char
cristy54a531d2009-10-21 17:58:01 +000079 *name,
cristy3ed852e2009-09-05 21:47:34 +000080 *pattern,
81 *value;
82
83 MagickBooleanType
cristy54a531d2009-10-21 17:58:01 +000084 exempt,
cristy3ed852e2009-09-05 21:47:34 +000085 stealth,
86 debug;
87
88 SemaphoreInfo
89 *semaphore;
90
91 unsigned long
92 signature;
93};
cristy54a531d2009-10-21 17:58:01 +000094
95typedef struct _PolicyMapInfo
96{
97 const PolicyDomain
98 domain;
99
100 const PolicyRights
101 rights;
102
103 const char
104 *name,
105 *pattern,
106 *value;
107} PolicyMapInfo;
cristy3ed852e2009-09-05 21:47:34 +0000108
109/*
110 Static declarations.
111*/
cristy54a531d2009-10-21 17:58:01 +0000112static const PolicyMapInfo
113 PolicyMap[] =
114 {
cristyfa378d92009-10-23 15:41:15 +0000115 { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
116 (const char *) NULL, (const char *) NULL }
cristy54a531d2009-10-21 17:58:01 +0000117 };
118
cristy3ed852e2009-09-05 21:47:34 +0000119static LinkedListInfo
120 *policy_list = (LinkedListInfo *) NULL;
121
122static SemaphoreInfo
123 *policy_semaphore = (SemaphoreInfo *) NULL;
124
125static volatile MagickBooleanType
126 instantiate_policy = MagickFalse;
127
128/*
129 Forward declarations.
130*/
131static MagickBooleanType
132 InitializePolicyList(ExceptionInfo *),
133 LoadPolicyLists(const char *,ExceptionInfo *);
134
135/*
136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137% %
138% %
139% %
cristydf1cc5f2009-10-19 16:02:33 +0000140+ D e s t r o y P o l i c y C o m p o n e n t %
cristy3ed852e2009-09-05 21:47:34 +0000141% %
142% %
143% %
144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145%
cristydf1cc5f2009-10-19 16:02:33 +0000146% DestroyPolicyComponent() destroys the policy component.
cristy3ed852e2009-09-05 21:47:34 +0000147%
cristydf1cc5f2009-10-19 16:02:33 +0000148% The format of the DestroyPolicyComponent method is:
cristy3ed852e2009-09-05 21:47:34 +0000149%
cristydf1cc5f2009-10-19 16:02:33 +0000150% DestroyPolicyComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000151%
152*/
153
154static void *DestroyPolicyElement(void *policy_info)
155{
156 register PolicyInfo
157 *p;
158
159 p=(PolicyInfo *) policy_info;
cristy54a531d2009-10-21 17:58:01 +0000160 if (p->exempt == MagickFalse)
161 {
162 if (p->value != (char *) NULL)
163 p->value=DestroyString(p->value);
164 if (p->pattern != (char *) NULL)
165 p->pattern=DestroyString(p->pattern);
166 if (p->name != (char *) NULL)
167 p->name=DestroyString(p->name);
168 if (p->path != (char *) NULL)
169 p->path=DestroyString(p->path);
170 }
cristy3ed852e2009-09-05 21:47:34 +0000171 p=(PolicyInfo *) RelinquishMagickMemory(p);
172 return((void *) NULL);
173}
174
cristydf1cc5f2009-10-19 16:02:33 +0000175MagickExport void DestroyPolicyComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000176{
177 AcquireSemaphoreInfo(&policy_semaphore);
178 if (policy_list != (LinkedListInfo *) NULL)
179 policy_list=DestroyLinkedList(policy_list,DestroyPolicyElement);
180 instantiate_policy=MagickFalse;
181 RelinquishSemaphoreInfo(policy_semaphore);
182 DestroySemaphoreInfo(&policy_semaphore);
183}
184
185/*
186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187% %
188% %
189% %
190+ G e t P o l i c y I n f o %
191% %
192% %
193% %
194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195%
196% GetPolicyInfo() searches the policy list for the specified name and if found
197% returns attributes for that policy.
198%
199% The format of the GetPolicyInfo method is:
200%
201% PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
202%
203% A description of each parameter follows:
204%
205% o name: the policy name.
206%
207% o exception: return any errors or warnings in this structure.
208%
209*/
210static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
211{
212 char
213 policyname[MaxTextExtent];
214
215 register PolicyInfo
216 *p;
217
218 register char
219 *q;
220
221 assert(exception != (ExceptionInfo *) NULL);
222 if ((policy_list == (LinkedListInfo *) NULL) ||
223 (instantiate_policy == MagickFalse))
224 if (InitializePolicyList(exception) == MagickFalse)
225 return((PolicyInfo *) NULL);
226 if ((policy_list == (LinkedListInfo *) NULL) ||
227 (IsLinkedListEmpty(policy_list) != MagickFalse))
228 return((PolicyInfo *) NULL);
229 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
230 return((PolicyInfo *) GetValueFromLinkedList(policy_list,0));
231 /*
232 Strip names of whitespace.
233 */
234 (void) CopyMagickString(policyname,name,MaxTextExtent);
235 for (q=policyname; *q != '\0'; q++)
236 {
237 if (isspace((int) ((unsigned char) *q)) == 0)
238 continue;
239 (void) CopyMagickString(q,q+1,MaxTextExtent);
240 q--;
241 }
242 /*
243 Search for policy tag.
244 */
245 AcquireSemaphoreInfo(&policy_semaphore);
246 ResetLinkedListIterator(policy_list);
247 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
248 while (p != (PolicyInfo *) NULL)
249 {
250 if (LocaleCompare(policyname,p->name) == 0)
251 break;
252 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
253 }
254 if (p == (PolicyInfo *) NULL)
255 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
256 "UnrecognizedPolicy","`%s'",name);
257 else
258 (void) InsertValueInLinkedList(policy_list,0,
259 RemoveElementByValueFromLinkedList(policy_list,p));
260 RelinquishSemaphoreInfo(policy_semaphore);
261 return(p);
262}
263
264/*
265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266% %
267% %
268% %
269% G e t P o l i c y I n f o L i s t %
270% %
271% %
272% %
273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274%
275% GetPolicyInfoList() returns any policies that match the specified pattern.
276%
277% The format of the GetPolicyInfoList function is:
278%
279% const PolicyInfo **GetPolicyInfoList(const char *pattern,
280% unsigned long *number_policies,ExceptionInfo *exception)
281%
282% A description of each parameter follows:
283%
284% o pattern: Specifies a pointer to a text string containing a pattern.
285%
286% o number_policies: returns the number of policies in the list.
287%
288% o exception: return any errors or warnings in this structure.
289%
290*/
291MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
292 unsigned long *number_policies,ExceptionInfo *exception)
293{
294 const PolicyInfo
295 **policies;
296
297 register const PolicyInfo
298 *p;
299
300 register long
301 i;
302
303 /*
304 Allocate policy list.
305 */
306 assert(pattern != (char *) NULL);
307 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
308 assert(number_policies != (unsigned long *) NULL);
309 *number_policies=0;
310 p=GetPolicyInfo("*",exception);
311 if (p == (const PolicyInfo *) NULL)
312 return((const PolicyInfo **) NULL);
313 policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
314 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
315 if (policies == (const PolicyInfo **) NULL)
316 return((const PolicyInfo **) NULL);
317 /*
318 Generate policy list.
319 */
320 AcquireSemaphoreInfo(&policy_semaphore);
321 ResetLinkedListIterator(policy_list);
322 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
323 for (i=0; p != (const PolicyInfo *) NULL; )
324 {
325 if ((p->stealth == MagickFalse) &&
326 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
327 policies[i++]=p;
328 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
329 }
330 RelinquishSemaphoreInfo(policy_semaphore);
331 policies[i]=(PolicyInfo *) NULL;
332 *number_policies=(unsigned long) i;
333 return(policies);
334}
335
336/*
337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
338% %
339% %
340% %
341% G e t P o l i c y L i s t %
342% %
343% %
344% %
345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346%
347% GetPolicyList() returns any policies that match the specified pattern.
348%
349% The format of the GetPolicyList function is:
350%
351% char **GetPolicyList(const char *pattern,unsigned long *number_policies,
352% ExceptionInfo *exception)
353%
354% A description of each parameter follows:
355%
356% o pattern: a pointer to a text string containing a pattern.
357%
358% o number_policies: returns the number of policies in the list.
359%
360% o exception: return any errors or warnings in this structure.
361%
362*/
363MagickExport char **GetPolicyList(const char *pattern,
364 unsigned long *number_policies,ExceptionInfo *exception)
365{
366 char
367 **policies;
368
369 register const PolicyInfo
370 *p;
371
372 register long
373 i;
374
375 /*
376 Allocate policy list.
377 */
378 assert(pattern != (char *) NULL);
379 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
380 assert(number_policies != (unsigned long *) NULL);
381 *number_policies=0;
382 p=GetPolicyInfo("*",exception);
383 if (p == (const PolicyInfo *) NULL)
384 return((char **) NULL);
385 policies=(char **) AcquireQuantumMemory((size_t)
386 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
387 if (policies == (char **) NULL)
388 return((char **) NULL);
389 /*
390 Generate policy list.
391 */
392 AcquireSemaphoreInfo(&policy_semaphore);
393 ResetLinkedListIterator(policy_list);
394 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
395 for (i=0; p != (const PolicyInfo *) NULL; )
396 {
397 if ((p->stealth == MagickFalse) &&
398 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
399 policies[i++]=ConstantString(p->name);
400 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
401 }
402 RelinquishSemaphoreInfo(policy_semaphore);
403 policies[i]=(char *) NULL;
404 *number_policies=(unsigned long) i;
405 return(policies);
406}
407
408/*
409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
410% %
411% %
412% %
413% G e t P o l i c y V a l u e %
414% %
415% %
416% %
417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418%
419% GetPolicyValue() returns the value associated with the named policy.
420%
421% The format of the GetPolicyValue method is:
422%
423% char *GetPolicyValue(const char *name)
424%
425% A description of each parameter follows:
426%
427% o policy_info: The policy info.
428%
429*/
430MagickExport char *GetPolicyValue(const char *name)
431{
432 const char
433 *value;
434
435 const PolicyInfo
436 *policy_info;
437
438 ExceptionInfo
439 *exception;
440
441 assert(name != (const char *) NULL);
442 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
443 exception=AcquireExceptionInfo();
444 policy_info=GetPolicyInfo(name,exception);
445 exception=DestroyExceptionInfo(exception);
446 if (policy_info == (PolicyInfo *) NULL)
447 return((char *) NULL);
448 value=policy_info->value;
449 if ((value == (const char *) NULL) || (*value == '\0'))
450 return((char *) NULL);
451 return(ConstantString(value));
452}
453
454/*
455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456% %
457% %
458% %
459+ I n i t i a l i z e P o l i c y L i s t %
460% %
461% %
462% %
463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464%
465% InitializePolicyList() initializes the policy list.
466%
467% The format of the InitializePolicyList method is:
468%
469% MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
470%
471% A description of each parameter follows.
472%
473% o exception: return any errors or warnings in this structure.
474%
475*/
476static MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
477{
478 if ((policy_list == (LinkedListInfo *) NULL) &&
479 (instantiate_policy == MagickFalse))
480 {
481 AcquireSemaphoreInfo(&policy_semaphore);
482 if ((policy_list == (LinkedListInfo *) NULL) &&
483 (instantiate_policy == MagickFalse))
484 {
485 (void) LoadPolicyLists(PolicyFilename,exception);
486 instantiate_policy=MagickTrue;
487 }
488 RelinquishSemaphoreInfo(policy_semaphore);
489 }
490 return(policy_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
491}
492
493/*
494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
495% %
496% %
497% %
cristydf1cc5f2009-10-19 16:02:33 +0000498+ I n s t a n t i a t e P o l i c y C o m p o n e n t %
cristy41c3c772009-10-19 02:17:37 +0000499% %
500% %
501% %
502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503%
cristydf1cc5f2009-10-19 16:02:33 +0000504% InstantiatePolicyComponent() instantiates the policy component.
cristy41c3c772009-10-19 02:17:37 +0000505%
cristydf1cc5f2009-10-19 16:02:33 +0000506% The format of the InstantiatePolicyComponent method is:
cristy41c3c772009-10-19 02:17:37 +0000507%
cristydf1cc5f2009-10-19 16:02:33 +0000508% MagickBooleanType InstantiatePolicyComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000509%
510*/
cristydf1cc5f2009-10-19 16:02:33 +0000511MagickExport MagickBooleanType InstantiatePolicyComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000512{
513 AcquireSemaphoreInfo(&policy_semaphore);
514 RelinquishSemaphoreInfo(policy_semaphore);
515 return(MagickTrue);
516}
517
518/*
519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520% %
521% %
522% %
cristy3ed852e2009-09-05 21:47:34 +0000523% I s R i g h t s A u t h o r i z e d %
524% %
525% %
526% %
527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528%
529% IsRightsAuthorized() returns MagickTrue if the policy authorizes the
530% requested rights for the specified domain.
531%
532% The format of the IsRightsAuthorized method is:
533%
534% MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
535% const PolicyRights rights,const char *pattern)
536%
537% A description of each parameter follows:
538%
539% o domain: the policy domain.
540%
541% o rights: the policy rights.
542%
543% o pattern: the coder, delegate, filter, or path pattern.
544%
545*/
546MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
547 const PolicyRights rights,const char *pattern)
548{
549 const PolicyInfo
550 *policy_info;
551
552 ExceptionInfo
553 *exception;
554
555 MagickBooleanType
556 authorized;
557
558 register PolicyInfo
559 *p;
560
561 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
562 "Domain: %s; rights=%s; pattern=\"%s\" ...",
563 MagickOptionToMnemonic(MagickPolicyDomainOptions,domain),
564 MagickOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
565 exception=AcquireExceptionInfo();
566 policy_info=GetPolicyInfo("*",exception);
567 exception=DestroyExceptionInfo(exception);
568 if (policy_info == (PolicyInfo *) NULL)
569 return(MagickTrue);
570 authorized=MagickTrue;
571 AcquireSemaphoreInfo(&policy_semaphore);
572 ResetLinkedListIterator(policy_list);
573 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
574 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
575 {
576 if ((p->domain == domain) &&
577 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
578 {
579 if (((rights & ReadPolicyRights) != 0) &&
580 ((p->rights & ReadPolicyRights) == 0))
581 authorized=MagickFalse;
582 if (((rights & WritePolicyRights) != 0) &&
583 ((p->rights & WritePolicyRights) == 0))
584 authorized=MagickFalse;
585 if (((rights & ExecutePolicyRights) != 0) &&
586 ((p->rights & ExecutePolicyRights) == 0))
587 authorized=MagickFalse;
588 }
589 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
590 }
591 RelinquishSemaphoreInfo(policy_semaphore);
592 return(authorized);
593}
594
595/*
596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597% %
598% %
599% %
600% L i s t P o l i c y I n f o %
601% %
602% %
603% %
604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
605%
606% ListPolicyInfo() lists policies to the specified file.
607%
608% The format of the ListPolicyInfo method is:
609%
610% MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
611%
612% A description of each parameter follows.
613%
614% o file: List policy names to this file handle.
615%
616% o exception: return any errors or warnings in this structure.
617%
618*/
619MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
620 ExceptionInfo *exception)
621{
622 const char
623 *path,
624 *domain;
625
626 const PolicyInfo
627 **policy_info;
628
629 register long
630 i;
631
632 unsigned long
633 number_policies;
634
635 /*
636 List name and attributes of each policy in the list.
637 */
638 if (file == (const FILE *) NULL)
639 file=stdout;
640 policy_info=GetPolicyInfoList("*",&number_policies,exception);
641 if (policy_info == (const PolicyInfo **) NULL)
642 return(MagickFalse);
643 path=(const char *) NULL;
644 for (i=0; i < (long) number_policies; i++)
645 {
646 if (policy_info[i]->stealth != MagickFalse)
647 continue;
648 if (((path == (const char *) NULL) ||
649 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
650 (policy_info[i]->path != (char *) NULL))
651 (void) fprintf(file,"\nPath: %s\n",policy_info[i]->path);
652 path=policy_info[i]->path;
653 domain=MagickOptionToMnemonic(MagickPolicyDomainOptions,
654 policy_info[i]->domain);
655 (void) fprintf(file," Policy: %s\n",domain);
656 if (policy_info[i]->domain == ResourcePolicyDomain)
657 {
658 if (policy_info[i]->name != (char *) NULL)
659 (void) fprintf(file," name: %s\n",policy_info[i]->name);
660 if (policy_info[i]->value != (char *) NULL)
661 (void) fprintf(file," value: %s\n",policy_info[i]->value);
662 }
663 else
664 {
665 (void) fprintf(file," rights: ");
666 if (policy_info[i]->rights == NoPolicyRights)
667 (void) fprintf(file,"None ");
668 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
669 (void) fprintf(file,"Read ");
670 if ((policy_info[i]->rights & WritePolicyRights) != 0)
671 (void) fprintf(file,"Write ");
672 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
673 (void) fprintf(file,"Execute ");
674 (void) fprintf(file,"\n");
675 if (policy_info[i]->pattern != (char *) NULL)
676 (void) fprintf(file," pattern: %s\n",policy_info[i]->pattern);
677 }
678 }
679 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
680 policy_info);
681 (void) fflush(file);
682 return(MagickTrue);
683}
684
685/*
686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687% %
688% %
689% %
690+ L o a d P o l i c y L i s t %
691% %
692% %
693% %
694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
695%
696% LoadPolicyList() loads the policy configuration file which provides a mapping
697% between policy attributes and a policy domain.
698%
699% The format of the LoadPolicyList method is:
700%
701% MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
702% const unsigned long depth,ExceptionInfo *exception)
703%
704% A description of each parameter follows:
705%
706% o xml: The policy list in XML format.
707%
708% o filename: The policy list filename.
709%
710% o depth: depth of <include /> statements.
711%
712% o exception: return any errors or warnings in this structure.
713%
714*/
715static MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
716 const unsigned long depth,ExceptionInfo *exception)
717{
718 char
719 keyword[MaxTextExtent],
720 *token;
721
722 PolicyInfo
723 *policy_info;
724
725 const char
726 *q;
727
728 MagickBooleanType
729 status;
730
731 /*
732 Load the policy map file.
733 */
734 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
735 "Loading policy file \"%s\" ...",filename);
736 if (xml == (char *) NULL)
737 return(MagickFalse);
738 if (policy_list == (LinkedListInfo *) NULL)
739 {
740 policy_list=NewLinkedList(0);
741 if (policy_list == (LinkedListInfo *) NULL)
742 {
743 ThrowFileException(exception,ResourceLimitError,
744 "MemoryAllocationFailed",filename);
745 return(MagickFalse);
746 }
747 }
748 status=MagickTrue;
749 policy_info=(PolicyInfo *) NULL;
750 token=AcquireString(xml);
751 for (q=(const char *) xml; *q != '\0'; )
752 {
753 /*
754 Interpret XML.
755 */
756 GetMagickToken(q,&q,token);
757 if (*token == '\0')
758 break;
759 (void) CopyMagickString(keyword,token,MaxTextExtent);
760 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
761 {
762 /*
763 Docdomain element.
764 */
765 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
766 GetMagickToken(q,&q,token);
767 continue;
768 }
769 if (LocaleNCompare(keyword,"<!--",4) == 0)
770 {
771 /*
772 Comment element.
773 */
774 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
775 GetMagickToken(q,&q,token);
776 continue;
777 }
778 if (LocaleCompare(keyword,"<include") == 0)
779 {
780 /*
781 Include element.
782 */
783 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
784 {
785 (void) CopyMagickString(keyword,token,MaxTextExtent);
786 GetMagickToken(q,&q,token);
787 if (*token != '=')
788 continue;
789 GetMagickToken(q,&q,token);
790 if (LocaleCompare(keyword,"file") == 0)
791 {
792 if (depth > 200)
793 (void) ThrowMagickException(exception,GetMagickModule(),
794 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
795 else
796 {
797 char
798 path[MaxTextExtent],
799 *xml;
800
801 GetPathComponent(filename,HeadPath,path);
802 if (*path != '\0')
803 (void) ConcatenateMagickString(path,DirectorySeparator,
804 MaxTextExtent);
805 if (*token == *DirectorySeparator)
806 (void) CopyMagickString(path,token,MaxTextExtent);
807 else
808 (void) ConcatenateMagickString(path,token,MaxTextExtent);
809 xml=FileToString(path,~0,exception);
810 if (xml != (char *) NULL)
811 {
812 status=LoadPolicyList(xml,path,depth+1,exception);
813 xml=(char *) RelinquishMagickMemory(xml);
814 }
815 }
816 }
817 }
818 continue;
819 }
820 if (LocaleCompare(keyword,"<policy") == 0)
821 {
822 /*
823 Policy element.
824 */
825 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
826 if (policy_info == (PolicyInfo *) NULL)
827 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
828 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
829 policy_info->path=ConstantString(filename);
cristy54a531d2009-10-21 17:58:01 +0000830 policy_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000831 policy_info->signature=MagickSignature;
832 continue;
833 }
834 if (policy_info == (PolicyInfo *) NULL)
835 continue;
836 if (LocaleCompare(keyword,"/>") == 0)
837 {
838 status=AppendValueToLinkedList(policy_list,policy_info);
839 if (status == MagickFalse)
840 (void) ThrowMagickException(exception,GetMagickModule(),
841 ResourceLimitError,"MemoryAllocationFailed","`%s'",
842 policy_info->name);
843 policy_info=(PolicyInfo *) NULL;
844 }
845 GetMagickToken(q,(const char **) NULL,token);
846 if (*token != '=')
847 continue;
848 GetMagickToken(q,&q,token);
849 GetMagickToken(q,&q,token);
850 switch (*keyword)
851 {
852 case 'D':
853 case 'd':
854 {
855 if (LocaleCompare((char *) keyword,"domain") == 0)
856 {
857 policy_info->domain=(PolicyDomain) ParseMagickOption(
858 MagickPolicyDomainOptions,MagickTrue,token);
859 break;
860 }
861 break;
862 }
863 case 'N':
864 case 'n':
865 {
866 if (LocaleCompare((char *) keyword,"name") == 0)
867 {
868 policy_info->name=ConstantString(token);
869 break;
870 }
871 break;
872 }
873 case 'P':
874 case 'p':
875 {
876 if (LocaleCompare((char *) keyword,"pattern") == 0)
877 {
878 policy_info->pattern=ConstantString(token);
879 break;
880 }
881 break;
882 }
883 case 'R':
884 case 'r':
885 {
886 if (LocaleCompare((char *) keyword,"rights") == 0)
887 {
888 policy_info->rights=(PolicyRights) ParseMagickOption(
889 MagickPolicyRightsOptions,MagickTrue,token);
890 break;
891 }
892 break;
893 }
894 case 'S':
895 case 's':
896 {
897 if (LocaleCompare((char *) keyword,"stealth") == 0)
898 {
899 policy_info->stealth=IsMagickTrue(token);
900 break;
901 }
902 break;
903 }
904 case 'V':
905 case 'v':
906 {
907 if (LocaleCompare((char *) keyword,"value") == 0)
908 {
909 policy_info->value=ConstantString(token);
910 break;
911 }
912 break;
913 }
914 default:
915 break;
916 }
917 }
918 token=(char *) RelinquishMagickMemory(token);
919 return(status);
920}
921
922/*
923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
924% %
925% %
926% %
927% L o a d P o l i c y L i s t s %
928% %
929% %
930% %
931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
932%
933% LoadPolicyList() loads one or more policy configuration file which provides a
934% mapping between policy attributes and a policy name.
935%
936% The format of the LoadPolicyLists method is:
937%
938% MagickBooleanType LoadPolicyLists(const char *filename,
939% ExceptionInfo *exception)
940%
941% A description of each parameter follows:
942%
943% o filename: the font file name.
944%
945% o exception: return any errors or warnings in this structure.
946%
947*/
948static MagickBooleanType LoadPolicyLists(const char *filename,
949 ExceptionInfo *exception)
950{
cristy3ed852e2009-09-05 21:47:34 +0000951 const StringInfo
952 *option;
953
954 LinkedListInfo
955 *options;
956
957 MagickStatusType
958 status;
959
cristy54a531d2009-10-21 17:58:01 +0000960 register long
961 i;
962
963 /*
964 Load built-in policy map.
965 */
cristy3ed852e2009-09-05 21:47:34 +0000966 status=MagickFalse;
cristy54a531d2009-10-21 17:58:01 +0000967 if (policy_list == (LinkedListInfo *) NULL)
968 {
969 policy_list=NewLinkedList(0);
970 if (policy_list == (LinkedListInfo *) NULL)
971 {
972 ThrowFileException(exception,ResourceLimitError,
973 "MemoryAllocationFailed",filename);
974 return(MagickFalse);
975 }
976 }
977 for (i=0; i < (long) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
978 {
979 PolicyInfo
980 *policy_info;
981
982 register const PolicyMapInfo
983 *p;
984
985 p=PolicyMap+i;
986 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
987 if (policy_info == (PolicyInfo *) NULL)
988 {
989 (void) ThrowMagickException(exception,GetMagickModule(),
990 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
991 continue;
992 }
993 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
994 policy_info->path=(char *) "[built-in]";
995 policy_info->domain=p->domain;
996 policy_info->rights=p->rights;
997 policy_info->name=(char *) p->name;
998 policy_info->pattern=(char *) p->pattern;
999 policy_info->value=(char *) p->value;
1000 policy_info->exempt=MagickTrue;
1001 policy_info->signature=MagickSignature;
1002 status=AppendValueToLinkedList(policy_list,policy_info);
1003 if (status == MagickFalse)
1004 (void) ThrowMagickException(exception,GetMagickModule(),
1005 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
1006 }
1007 /*
1008 Load external policy map.
1009 */
cristy3ed852e2009-09-05 21:47:34 +00001010 options=GetConfigureOptions(filename,exception);
1011 option=(const StringInfo *) GetNextValueInLinkedList(options);
1012 while (option != (const StringInfo *) NULL)
1013 {
1014 status|=LoadPolicyList((const char *) GetStringInfoDatum(option),
1015 GetStringInfoPath(option),0,exception);
1016 option=(const StringInfo *) GetNextValueInLinkedList(options);
1017 }
1018 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +00001019 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001020}