blob: fd31a38d52d76c903b733888d7af4c97c0970e52 [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% %
cristy3ed852e2009-09-05 21:47:34 +0000140+ G e t P o l i c y I n f o %
141% %
142% %
143% %
144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145%
146% GetPolicyInfo() searches the policy list for the specified name and if found
147% returns attributes for that policy.
148%
149% The format of the GetPolicyInfo method is:
150%
151% PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
152%
153% A description of each parameter follows:
154%
155% o name: the policy name.
156%
157% o exception: return any errors or warnings in this structure.
158%
159*/
160static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
161{
162 char
163 policyname[MaxTextExtent];
164
165 register PolicyInfo
166 *p;
167
168 register char
169 *q;
170
171 assert(exception != (ExceptionInfo *) NULL);
172 if ((policy_list == (LinkedListInfo *) NULL) ||
173 (instantiate_policy == MagickFalse))
174 if (InitializePolicyList(exception) == MagickFalse)
175 return((PolicyInfo *) NULL);
176 if ((policy_list == (LinkedListInfo *) NULL) ||
177 (IsLinkedListEmpty(policy_list) != MagickFalse))
178 return((PolicyInfo *) NULL);
179 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
180 return((PolicyInfo *) GetValueFromLinkedList(policy_list,0));
181 /*
182 Strip names of whitespace.
183 */
184 (void) CopyMagickString(policyname,name,MaxTextExtent);
185 for (q=policyname; *q != '\0'; q++)
186 {
187 if (isspace((int) ((unsigned char) *q)) == 0)
188 continue;
189 (void) CopyMagickString(q,q+1,MaxTextExtent);
190 q--;
191 }
192 /*
193 Search for policy tag.
194 */
195 AcquireSemaphoreInfo(&policy_semaphore);
196 ResetLinkedListIterator(policy_list);
197 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
198 while (p != (PolicyInfo *) NULL)
199 {
200 if (LocaleCompare(policyname,p->name) == 0)
201 break;
202 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
203 }
204 if (p == (PolicyInfo *) NULL)
205 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
206 "UnrecognizedPolicy","`%s'",name);
207 else
208 (void) InsertValueInLinkedList(policy_list,0,
209 RemoveElementByValueFromLinkedList(policy_list,p));
210 RelinquishSemaphoreInfo(policy_semaphore);
211 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,
230% unsigned long *number_policies,ExceptionInfo *exception)
231%
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,
242 unsigned long *number_policies,ExceptionInfo *exception)
243{
244 const PolicyInfo
245 **policies;
246
247 register const PolicyInfo
248 *p;
249
250 register long
251 i;
252
253 /*
254 Allocate policy list.
255 */
256 assert(pattern != (char *) NULL);
257 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
258 assert(number_policies != (unsigned long *) NULL);
259 *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 */
270 AcquireSemaphoreInfo(&policy_semaphore);
271 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 }
280 RelinquishSemaphoreInfo(policy_semaphore);
281 policies[i]=(PolicyInfo *) NULL;
282 *number_policies=(unsigned long) i;
283 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%
301% char **GetPolicyList(const char *pattern,unsigned long *number_policies,
302% 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,
314 unsigned long *number_policies,ExceptionInfo *exception)
315{
316 char
317 **policies;
318
319 register const PolicyInfo
320 *p;
321
322 register long
323 i;
324
325 /*
326 Allocate policy list.
327 */
328 assert(pattern != (char *) NULL);
329 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
330 assert(number_policies != (unsigned long *) NULL);
331 *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 */
342 AcquireSemaphoreInfo(&policy_semaphore);
343 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 }
352 RelinquishSemaphoreInfo(policy_semaphore);
353 policies[i]=(char *) NULL;
354 *number_policies=(unsigned long) i;
355 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 {
431 AcquireSemaphoreInfo(&policy_semaphore);
432 if ((policy_list == (LinkedListInfo *) NULL) &&
433 (instantiate_policy == MagickFalse))
434 {
435 (void) LoadPolicyLists(PolicyFilename,exception);
436 instantiate_policy=MagickTrue;
437 }
438 RelinquishSemaphoreInfo(policy_semaphore);
439 }
440 return(policy_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
441}
442
443/*
444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445% %
446% %
447% %
cristy3ed852e2009-09-05 21:47:34 +0000448% I s R i g h t s A u t h o r i z e d %
449% %
450% %
451% %
452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453%
454% IsRightsAuthorized() returns MagickTrue if the policy authorizes the
455% requested rights for the specified domain.
456%
457% The format of the IsRightsAuthorized method is:
458%
459% MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
460% const PolicyRights rights,const char *pattern)
461%
462% A description of each parameter follows:
463%
464% o domain: the policy domain.
465%
466% o rights: the policy rights.
467%
468% o pattern: the coder, delegate, filter, or path pattern.
469%
470*/
471MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
472 const PolicyRights rights,const char *pattern)
473{
474 const PolicyInfo
475 *policy_info;
476
477 ExceptionInfo
478 *exception;
479
480 MagickBooleanType
481 authorized;
482
483 register PolicyInfo
484 *p;
485
486 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
487 "Domain: %s; rights=%s; pattern=\"%s\" ...",
488 MagickOptionToMnemonic(MagickPolicyDomainOptions,domain),
489 MagickOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
490 exception=AcquireExceptionInfo();
491 policy_info=GetPolicyInfo("*",exception);
492 exception=DestroyExceptionInfo(exception);
493 if (policy_info == (PolicyInfo *) NULL)
494 return(MagickTrue);
495 authorized=MagickTrue;
496 AcquireSemaphoreInfo(&policy_semaphore);
497 ResetLinkedListIterator(policy_list);
498 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
499 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
500 {
501 if ((p->domain == domain) &&
502 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
503 {
504 if (((rights & ReadPolicyRights) != 0) &&
505 ((p->rights & ReadPolicyRights) == 0))
506 authorized=MagickFalse;
507 if (((rights & WritePolicyRights) != 0) &&
508 ((p->rights & WritePolicyRights) == 0))
509 authorized=MagickFalse;
510 if (((rights & ExecutePolicyRights) != 0) &&
511 ((p->rights & ExecutePolicyRights) == 0))
512 authorized=MagickFalse;
513 }
514 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
515 }
516 RelinquishSemaphoreInfo(policy_semaphore);
517 return(authorized);
518}
519
520/*
521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522% %
523% %
524% %
525% L i s t P o l i c y I n f o %
526% %
527% %
528% %
529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530%
531% ListPolicyInfo() lists policies to the specified file.
532%
533% The format of the ListPolicyInfo method is:
534%
535% MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
536%
537% A description of each parameter follows.
538%
539% o file: List policy names to this file handle.
540%
541% o exception: return any errors or warnings in this structure.
542%
543*/
544MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
545 ExceptionInfo *exception)
546{
547 const char
548 *path,
549 *domain;
550
551 const PolicyInfo
552 **policy_info;
553
554 register long
555 i;
556
557 unsigned long
558 number_policies;
559
560 /*
561 List name and attributes of each policy in the list.
562 */
563 if (file == (const FILE *) NULL)
564 file=stdout;
565 policy_info=GetPolicyInfoList("*",&number_policies,exception);
566 if (policy_info == (const PolicyInfo **) NULL)
567 return(MagickFalse);
568 path=(const char *) NULL;
569 for (i=0; i < (long) number_policies; i++)
570 {
571 if (policy_info[i]->stealth != MagickFalse)
572 continue;
573 if (((path == (const char *) NULL) ||
574 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
575 (policy_info[i]->path != (char *) NULL))
576 (void) fprintf(file,"\nPath: %s\n",policy_info[i]->path);
577 path=policy_info[i]->path;
578 domain=MagickOptionToMnemonic(MagickPolicyDomainOptions,
579 policy_info[i]->domain);
580 (void) fprintf(file," Policy: %s\n",domain);
581 if (policy_info[i]->domain == ResourcePolicyDomain)
582 {
583 if (policy_info[i]->name != (char *) NULL)
584 (void) fprintf(file," name: %s\n",policy_info[i]->name);
585 if (policy_info[i]->value != (char *) NULL)
586 (void) fprintf(file," value: %s\n",policy_info[i]->value);
587 }
588 else
589 {
590 (void) fprintf(file," rights: ");
591 if (policy_info[i]->rights == NoPolicyRights)
592 (void) fprintf(file,"None ");
593 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
594 (void) fprintf(file,"Read ");
595 if ((policy_info[i]->rights & WritePolicyRights) != 0)
596 (void) fprintf(file,"Write ");
597 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
598 (void) fprintf(file,"Execute ");
599 (void) fprintf(file,"\n");
600 if (policy_info[i]->pattern != (char *) NULL)
601 (void) fprintf(file," pattern: %s\n",policy_info[i]->pattern);
602 }
603 }
604 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
605 policy_info);
606 (void) fflush(file);
607 return(MagickTrue);
608}
609
610/*
611%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612% %
613% %
614% %
615+ L o a d P o l i c y L i s t %
616% %
617% %
618% %
619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
620%
621% LoadPolicyList() loads the policy configuration file which provides a mapping
622% between policy attributes and a policy domain.
623%
624% The format of the LoadPolicyList method is:
625%
626% MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
627% const unsigned long depth,ExceptionInfo *exception)
628%
629% A description of each parameter follows:
630%
631% o xml: The policy list in XML format.
632%
633% o filename: The policy list filename.
634%
635% o depth: depth of <include /> statements.
636%
637% o exception: return any errors or warnings in this structure.
638%
639*/
640static MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
641 const unsigned long depth,ExceptionInfo *exception)
642{
643 char
644 keyword[MaxTextExtent],
645 *token;
646
647 PolicyInfo
648 *policy_info;
649
650 const char
651 *q;
652
653 MagickBooleanType
654 status;
655
656 /*
657 Load the policy map file.
658 */
659 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
660 "Loading policy file \"%s\" ...",filename);
661 if (xml == (char *) NULL)
662 return(MagickFalse);
663 if (policy_list == (LinkedListInfo *) NULL)
664 {
665 policy_list=NewLinkedList(0);
666 if (policy_list == (LinkedListInfo *) NULL)
667 {
668 ThrowFileException(exception,ResourceLimitError,
669 "MemoryAllocationFailed",filename);
670 return(MagickFalse);
671 }
672 }
673 status=MagickTrue;
674 policy_info=(PolicyInfo *) NULL;
675 token=AcquireString(xml);
676 for (q=(const char *) xml; *q != '\0'; )
677 {
678 /*
679 Interpret XML.
680 */
681 GetMagickToken(q,&q,token);
682 if (*token == '\0')
683 break;
684 (void) CopyMagickString(keyword,token,MaxTextExtent);
685 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
686 {
687 /*
688 Docdomain element.
689 */
690 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
691 GetMagickToken(q,&q,token);
692 continue;
693 }
694 if (LocaleNCompare(keyword,"<!--",4) == 0)
695 {
696 /*
697 Comment element.
698 */
699 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
700 GetMagickToken(q,&q,token);
701 continue;
702 }
703 if (LocaleCompare(keyword,"<include") == 0)
704 {
705 /*
706 Include element.
707 */
708 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
709 {
710 (void) CopyMagickString(keyword,token,MaxTextExtent);
711 GetMagickToken(q,&q,token);
712 if (*token != '=')
713 continue;
714 GetMagickToken(q,&q,token);
715 if (LocaleCompare(keyword,"file") == 0)
716 {
717 if (depth > 200)
718 (void) ThrowMagickException(exception,GetMagickModule(),
719 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
720 else
721 {
722 char
723 path[MaxTextExtent],
724 *xml;
725
726 GetPathComponent(filename,HeadPath,path);
727 if (*path != '\0')
728 (void) ConcatenateMagickString(path,DirectorySeparator,
729 MaxTextExtent);
730 if (*token == *DirectorySeparator)
731 (void) CopyMagickString(path,token,MaxTextExtent);
732 else
733 (void) ConcatenateMagickString(path,token,MaxTextExtent);
734 xml=FileToString(path,~0,exception);
735 if (xml != (char *) NULL)
736 {
737 status=LoadPolicyList(xml,path,depth+1,exception);
738 xml=(char *) RelinquishMagickMemory(xml);
739 }
740 }
741 }
742 }
743 continue;
744 }
745 if (LocaleCompare(keyword,"<policy") == 0)
746 {
747 /*
748 Policy element.
749 */
750 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
751 if (policy_info == (PolicyInfo *) NULL)
752 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
753 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
754 policy_info->path=ConstantString(filename);
cristy54a531d2009-10-21 17:58:01 +0000755 policy_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000756 policy_info->signature=MagickSignature;
757 continue;
758 }
759 if (policy_info == (PolicyInfo *) NULL)
760 continue;
761 if (LocaleCompare(keyword,"/>") == 0)
762 {
763 status=AppendValueToLinkedList(policy_list,policy_info);
764 if (status == MagickFalse)
765 (void) ThrowMagickException(exception,GetMagickModule(),
766 ResourceLimitError,"MemoryAllocationFailed","`%s'",
767 policy_info->name);
768 policy_info=(PolicyInfo *) NULL;
769 }
770 GetMagickToken(q,(const char **) NULL,token);
771 if (*token != '=')
772 continue;
773 GetMagickToken(q,&q,token);
774 GetMagickToken(q,&q,token);
775 switch (*keyword)
776 {
777 case 'D':
778 case 'd':
779 {
780 if (LocaleCompare((char *) keyword,"domain") == 0)
781 {
782 policy_info->domain=(PolicyDomain) ParseMagickOption(
783 MagickPolicyDomainOptions,MagickTrue,token);
784 break;
785 }
786 break;
787 }
788 case 'N':
789 case 'n':
790 {
791 if (LocaleCompare((char *) keyword,"name") == 0)
792 {
793 policy_info->name=ConstantString(token);
794 break;
795 }
796 break;
797 }
798 case 'P':
799 case 'p':
800 {
801 if (LocaleCompare((char *) keyword,"pattern") == 0)
802 {
803 policy_info->pattern=ConstantString(token);
804 break;
805 }
806 break;
807 }
808 case 'R':
809 case 'r':
810 {
811 if (LocaleCompare((char *) keyword,"rights") == 0)
812 {
813 policy_info->rights=(PolicyRights) ParseMagickOption(
814 MagickPolicyRightsOptions,MagickTrue,token);
815 break;
816 }
817 break;
818 }
819 case 'S':
820 case 's':
821 {
822 if (LocaleCompare((char *) keyword,"stealth") == 0)
823 {
824 policy_info->stealth=IsMagickTrue(token);
825 break;
826 }
827 break;
828 }
829 case 'V':
830 case 'v':
831 {
832 if (LocaleCompare((char *) keyword,"value") == 0)
833 {
834 policy_info->value=ConstantString(token);
835 break;
836 }
837 break;
838 }
839 default:
840 break;
841 }
842 }
843 token=(char *) RelinquishMagickMemory(token);
844 return(status);
845}
846
847/*
848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
849% %
850% %
851% %
852% L o a d P o l i c y L i s t s %
853% %
854% %
855% %
856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857%
858% LoadPolicyList() loads one or more policy configuration file which provides a
859% mapping between policy attributes and a policy name.
860%
861% The format of the LoadPolicyLists method is:
862%
863% MagickBooleanType LoadPolicyLists(const char *filename,
864% ExceptionInfo *exception)
865%
866% A description of each parameter follows:
867%
868% o filename: the font file name.
869%
870% o exception: return any errors or warnings in this structure.
871%
872*/
873static MagickBooleanType LoadPolicyLists(const char *filename,
874 ExceptionInfo *exception)
875{
cristy3ed852e2009-09-05 21:47:34 +0000876 const StringInfo
877 *option;
878
879 LinkedListInfo
880 *options;
881
882 MagickStatusType
883 status;
884
cristy54a531d2009-10-21 17:58:01 +0000885 register long
886 i;
887
888 /*
889 Load built-in policy map.
890 */
cristy3ed852e2009-09-05 21:47:34 +0000891 status=MagickFalse;
cristy54a531d2009-10-21 17:58:01 +0000892 if (policy_list == (LinkedListInfo *) NULL)
893 {
894 policy_list=NewLinkedList(0);
895 if (policy_list == (LinkedListInfo *) NULL)
896 {
897 ThrowFileException(exception,ResourceLimitError,
898 "MemoryAllocationFailed",filename);
899 return(MagickFalse);
900 }
901 }
902 for (i=0; i < (long) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
903 {
904 PolicyInfo
905 *policy_info;
906
907 register const PolicyMapInfo
908 *p;
909
910 p=PolicyMap+i;
911 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
912 if (policy_info == (PolicyInfo *) NULL)
913 {
914 (void) ThrowMagickException(exception,GetMagickModule(),
915 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
916 continue;
917 }
918 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
919 policy_info->path=(char *) "[built-in]";
920 policy_info->domain=p->domain;
921 policy_info->rights=p->rights;
922 policy_info->name=(char *) p->name;
923 policy_info->pattern=(char *) p->pattern;
924 policy_info->value=(char *) p->value;
925 policy_info->exempt=MagickTrue;
926 policy_info->signature=MagickSignature;
927 status=AppendValueToLinkedList(policy_list,policy_info);
928 if (status == MagickFalse)
929 (void) ThrowMagickException(exception,GetMagickModule(),
930 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
931 }
932 /*
933 Load external policy map.
934 */
cristy3ed852e2009-09-05 21:47:34 +0000935 options=GetConfigureOptions(filename,exception);
936 option=(const StringInfo *) GetNextValueInLinkedList(options);
937 while (option != (const StringInfo *) NULL)
938 {
939 status|=LoadPolicyList((const char *) GetStringInfoDatum(option),
940 GetStringInfoPath(option),0,exception);
941 option=(const StringInfo *) GetNextValueInLinkedList(options);
942 }
943 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +0000944 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000945}
cristyf34a1452009-10-24 22:29:27 +0000946
947/*
948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
949% %
950% %
951% %
952+ P o l i c y C o m p o n e n t G e n e s i s %
953% %
954% %
955% %
956%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957%
958% PolicyComponentGenesis() instantiates the policy component.
959%
960% The format of the PolicyComponentGenesis method is:
961%
962% MagickBooleanType PolicyComponentGenesis(void)
963%
964*/
965MagickExport MagickBooleanType PolicyComponentGenesis(void)
966{
967 AcquireSemaphoreInfo(&policy_semaphore);
968 RelinquishSemaphoreInfo(policy_semaphore);
969 return(MagickTrue);
970}
971
972/*
973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974% %
975% %
976% %
977+ P o l i c y C o m p o n e n t T e r m i n u s %
978% %
979% %
980% %
981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982%
983% PolicyComponentTerminus() destroys the policy component.
984%
985% The format of the PolicyComponentTerminus method is:
986%
987% PolicyComponentTerminus(void)
988%
989*/
990
991static void *DestroyPolicyElement(void *policy_info)
992{
993 register PolicyInfo
994 *p;
995
996 p=(PolicyInfo *) policy_info;
997 if (p->exempt == MagickFalse)
998 {
999 if (p->value != (char *) NULL)
1000 p->value=DestroyString(p->value);
1001 if (p->pattern != (char *) NULL)
1002 p->pattern=DestroyString(p->pattern);
1003 if (p->name != (char *) NULL)
1004 p->name=DestroyString(p->name);
1005 if (p->path != (char *) NULL)
1006 p->path=DestroyString(p->path);
1007 }
1008 p=(PolicyInfo *) RelinquishMagickMemory(p);
1009 return((void *) NULL);
1010}
1011
1012MagickExport void PolicyComponentTerminus(void)
1013{
1014 AcquireSemaphoreInfo(&policy_semaphore);
1015 if (policy_list != (LinkedListInfo *) NULL)
1016 policy_list=DestroyLinkedList(policy_list,DestroyPolicyElement);
1017 instantiate_policy=MagickFalse;
1018 RelinquishSemaphoreInfo(policy_semaphore);
1019 DestroySemaphoreInfo(&policy_semaphore);
1020}