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