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