• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2016 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 "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 
63 /*
64   Define declarations.
65 */
66 #define PolicyFilename  "policy.xml"
67 
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 
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 
129 /*
130   Forward declarations.
131 */
132 static MagickBooleanType
133   IsPolicyCacheInstantiated(ExceptionInfo *),
134   LoadPolicyCache(LinkedListInfo *,const char *,const char *,const size_t,
135     ExceptionInfo *);
136 
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 */
AcquirePolicyCache(const char * filename,ExceptionInfo * exception)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 
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 */
GetPolicyInfo(const char * name,ExceptionInfo * exception)262 static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
263 {
264   char
265     policyname[MagickPathExtent];
266 
267   register PolicyInfo
268     *p;
269 
270   register char
271     *q;
272 
273   assert(exception != (ExceptionInfo *) NULL);
274   if (IsPolicyCacheInstantiated(exception) == MagickFalse)
275     return((PolicyInfo *) NULL);
276   /*
277     Strip names of whitespace.
278   */
279   *policyname='\0';
280   if (name != (const char *) NULL)
281     (void) CopyMagickString(policyname,name,MagickPathExtent);
282   for (q=policyname; *q != '\0'; q++)
283   {
284     if (isspace((int) ((unsigned char) *q)) == 0)
285       continue;
286     (void) CopyMagickString(q,q+1,MagickPathExtent);
287     q--;
288   }
289   /*
290     Search for policy tag.
291   */
292   LockSemaphoreInfo(policy_semaphore);
293   ResetLinkedListIterator(policy_cache);
294   p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
295   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
296     {
297       UnlockSemaphoreInfo(policy_semaphore);
298       return(p);
299     }
300   while (p != (PolicyInfo *) NULL)
301   {
302     if (LocaleCompare(policyname,p->name) == 0)
303       break;
304     p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
305   }
306   if (p != (PolicyInfo *) NULL)
307     (void) InsertValueInLinkedList(policy_cache,0,
308       RemoveElementByValueFromLinkedList(policy_cache,p));
309   UnlockSemaphoreInfo(policy_semaphore);
310   return(p);
311 }
312 
313 /*
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 %                                                                             %
316 %                                                                             %
317 %                                                                             %
318 %   G e t P o l i c y I n f o L i s t                                         %
319 %                                                                             %
320 %                                                                             %
321 %                                                                             %
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 %
324 %  GetPolicyInfoList() returns any policies that match the specified pattern.
325 %
326 %  The format of the GetPolicyInfoList function is:
327 %
328 %      const PolicyInfo **GetPolicyInfoList(const char *pattern,
329 %        size_t *number_policies,ExceptionInfo *exception)
330 %
331 %  A description of each parameter follows:
332 %
333 %    o pattern: Specifies a pointer to a text string containing a pattern.
334 %
335 %    o number_policies:  returns the number of policies in the list.
336 %
337 %    o exception: return any errors or warnings in this structure.
338 %
339 */
GetPolicyInfoList(const char * pattern,size_t * number_policies,ExceptionInfo * exception)340 MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
341   size_t *number_policies,ExceptionInfo *exception)
342 {
343   const PolicyInfo
344     **policies;
345 
346   register const PolicyInfo
347     *p;
348 
349   register ssize_t
350     i;
351 
352   /*
353     Allocate policy list.
354   */
355   assert(pattern != (char *) NULL);
356   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
357   assert(number_policies != (size_t *) NULL);
358   *number_policies=0;
359   p=GetPolicyInfo("*",exception);
360   if (p == (const PolicyInfo *) NULL)
361     return((const PolicyInfo **) NULL);
362   policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
363     GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
364   if (policies == (const PolicyInfo **) NULL)
365     return((const PolicyInfo **) NULL);
366   /*
367     Generate policy list.
368   */
369   LockSemaphoreInfo(policy_semaphore);
370   ResetLinkedListIterator(policy_cache);
371   p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
372   for (i=0; p != (const PolicyInfo *) NULL; )
373   {
374     if ((p->stealth == MagickFalse) &&
375         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
376       policies[i++]=p;
377     p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
378   }
379   UnlockSemaphoreInfo(policy_semaphore);
380   policies[i]=(PolicyInfo *) NULL;
381   *number_policies=(size_t) i;
382   return(policies);
383 }
384 
385 /*
386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 %                                                                             %
388 %                                                                             %
389 %                                                                             %
390 %   G e t P o l i c y L i s t                                                 %
391 %                                                                             %
392 %                                                                             %
393 %                                                                             %
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 %
396 %  GetPolicyList() returns any policies that match the specified pattern.
397 %
398 %  The format of the GetPolicyList function is:
399 %
400 %      char **GetPolicyList(const char *pattern,size_t *number_policies,
401 %        ExceptionInfo *exception)
402 %
403 %  A description of each parameter follows:
404 %
405 %    o pattern: a pointer to a text string containing a pattern.
406 %
407 %    o number_policies:  returns the number of policies in the list.
408 %
409 %    o exception: return any errors or warnings in this structure.
410 %
411 */
GetPolicyList(const char * pattern,size_t * number_policies,ExceptionInfo * exception)412 MagickExport char **GetPolicyList(const char *pattern,
413   size_t *number_policies,ExceptionInfo *exception)
414 {
415   char
416     **policies;
417 
418   register const PolicyInfo
419     *p;
420 
421   register ssize_t
422     i;
423 
424   /*
425     Allocate policy list.
426   */
427   assert(pattern != (char *) NULL);
428   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
429   assert(number_policies != (size_t *) NULL);
430   *number_policies=0;
431   p=GetPolicyInfo("*",exception);
432   if (p == (const PolicyInfo *) NULL)
433     return((char **) NULL);
434   policies=(char **) AcquireQuantumMemory((size_t)
435     GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
436   if (policies == (char **) NULL)
437     return((char **) NULL);
438   /*
439     Generate policy list.
440   */
441   LockSemaphoreInfo(policy_semaphore);
442   ResetLinkedListIterator(policy_cache);
443   p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
444   for (i=0; p != (const PolicyInfo *) NULL; )
445   {
446     if ((p->stealth == MagickFalse) &&
447         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
448       policies[i++]=ConstantString(p->name);
449     p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
450   }
451   UnlockSemaphoreInfo(policy_semaphore);
452   policies[i]=(char *) NULL;
453   *number_policies=(size_t) i;
454   return(policies);
455 }
456 
457 /*
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 %                                                                             %
460 %                                                                             %
461 %                                                                             %
462 %   G e t P o l i c y V a l u e                                               %
463 %                                                                             %
464 %                                                                             %
465 %                                                                             %
466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467 %
468 %  GetPolicyValue() returns the value associated with the named policy.
469 %
470 %  The format of the GetPolicyValue method is:
471 %
472 %      char *GetPolicyValue(const char *name)
473 %
474 %  A description of each parameter follows:
475 %
476 %    o policy_info:  The policy info.
477 %
478 */
GetPolicyValue(const char * name)479 MagickExport char *GetPolicyValue(const char *name)
480 {
481   const char
482     *value;
483 
484   const PolicyInfo
485     *policy_info;
486 
487   ExceptionInfo
488     *exception;
489 
490   assert(name != (const char *) NULL);
491   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
492   exception=AcquireExceptionInfo();
493   policy_info=GetPolicyInfo(name,exception);
494   exception=DestroyExceptionInfo(exception);
495   if (policy_info == (PolicyInfo *) NULL)
496     return((char *) NULL);
497   value=policy_info->value;
498   if ((value == (const char *) NULL) || (*value == '\0'))
499     return((char *) NULL);
500   return(ConstantString(value));
501 }
502 
503 /*
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 %                                                                             %
506 %                                                                             %
507 %                                                                             %
508 +   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                         %
509 %                                                                             %
510 %                                                                             %
511 %                                                                             %
512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 %
514 %  IsPolicyCacheInstantiated() determines if the policy list is instantiated.
515 %  If not, it instantiates the list and returns it.
516 %
517 %  The format of the IsPolicyInstantiated method is:
518 %
519 %      MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
520 %
521 %  A description of each parameter follows.
522 %
523 %    o exception: return any errors or warnings in this structure.
524 %
525 */
IsPolicyCacheInstantiated(ExceptionInfo * exception)526 static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
527 {
528   if (policy_cache == (LinkedListInfo *) NULL)
529     {
530       if (policy_semaphore == (SemaphoreInfo *) NULL)
531         ActivateSemaphoreInfo(&policy_semaphore);
532       LockSemaphoreInfo(policy_semaphore);
533       if (policy_cache == (LinkedListInfo *) NULL)
534         policy_cache=AcquirePolicyCache(PolicyFilename,exception);
535       UnlockSemaphoreInfo(policy_semaphore);
536     }
537   return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
538 }
539 
540 /*
541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
542 %                                                                             %
543 %                                                                             %
544 %                                                                             %
545 %   I s R i g h t s A u t h o r i z e d                                       %
546 %                                                                             %
547 %                                                                             %
548 %                                                                             %
549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 %
551 %  IsRightsAuthorized() returns MagickTrue if the policy authorizes the
552 %  requested rights for the specified domain.
553 %
554 %  The format of the IsRightsAuthorized method is:
555 %
556 %      MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
557 %        const PolicyRights rights,const char *pattern)
558 %
559 %  A description of each parameter follows:
560 %
561 %    o domain: the policy domain.
562 %
563 %    o rights: the policy rights.
564 %
565 %    o pattern: the coder, delegate, filter, or path pattern.
566 %
567 */
IsRightsAuthorized(const PolicyDomain domain,const PolicyRights rights,const char * pattern)568 MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
569   const PolicyRights rights,const char *pattern)
570 {
571   const PolicyInfo
572     *policy_info;
573 
574   ExceptionInfo
575     *exception;
576 
577   MagickBooleanType
578     authorized;
579 
580   register PolicyInfo
581     *p;
582 
583   (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
584     "Domain: %s; rights=%s; pattern=\"%s\" ...",
585     CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
586     CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
587   exception=AcquireExceptionInfo();
588   policy_info=GetPolicyInfo("*",exception);
589   exception=DestroyExceptionInfo(exception);
590   if (policy_info == (PolicyInfo *) NULL)
591     return(MagickTrue);
592   authorized=MagickTrue;
593   LockSemaphoreInfo(policy_semaphore);
594   ResetLinkedListIterator(policy_cache);
595   p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
596   while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
597   {
598     if ((p->domain == domain) &&
599         (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
600       {
601         if (((rights & ReadPolicyRights) != 0) &&
602             ((p->rights & ReadPolicyRights) == 0))
603           authorized=MagickFalse;
604         if (((rights & WritePolicyRights) != 0) &&
605             ((p->rights & WritePolicyRights) == 0))
606           authorized=MagickFalse;
607         if (((rights & ExecutePolicyRights) != 0) &&
608             ((p->rights & ExecutePolicyRights) == 0))
609           authorized=MagickFalse;
610       }
611     p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
612   }
613   UnlockSemaphoreInfo(policy_semaphore);
614   return(authorized);
615 }
616 
617 /*
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %                                                                             %
620 %                                                                             %
621 %                                                                             %
622 %  L i s t P o l i c y I n f o                                                %
623 %                                                                             %
624 %                                                                             %
625 %                                                                             %
626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 %
628 %  ListPolicyInfo() lists policies to the specified file.
629 %
630 %  The format of the ListPolicyInfo method is:
631 %
632 %      MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
633 %
634 %  A description of each parameter follows.
635 %
636 %    o file:  List policy names to this file handle.
637 %
638 %    o exception: return any errors or warnings in this structure.
639 %
640 */
ListPolicyInfo(FILE * file,ExceptionInfo * exception)641 MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
642   ExceptionInfo *exception)
643 {
644   const char
645     *path,
646     *domain;
647 
648   const PolicyInfo
649     **policy_info;
650 
651   register ssize_t
652     i;
653 
654   size_t
655     number_policies;
656 
657   /*
658     List name and attributes of each policy in the list.
659   */
660   if (file == (const FILE *) NULL)
661     file=stdout;
662   policy_info=GetPolicyInfoList("*",&number_policies,exception);
663   if (policy_info == (const PolicyInfo **) NULL)
664     return(MagickFalse);
665   path=(const char *) NULL;
666   for (i=0; i < (ssize_t) number_policies; i++)
667   {
668     if (policy_info[i]->stealth != MagickFalse)
669       continue;
670     if (((path == (const char *) NULL) ||
671          (LocaleCompare(path,policy_info[i]->path) != 0)) &&
672          (policy_info[i]->path != (char *) NULL))
673       (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
674     path=policy_info[i]->path;
675     domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
676       policy_info[i]->domain);
677     (void) FormatLocaleFile(file,"  Policy: %s\n",domain);
678     if ((policy_info[i]->domain == CachePolicyDomain) ||
679         (policy_info[i]->domain == ResourcePolicyDomain) ||
680         (policy_info[i]->domain == SystemPolicyDomain))
681       {
682         if (policy_info[i]->name != (char *) NULL)
683           (void) FormatLocaleFile(file,"    name: %s\n",policy_info[i]->name);
684         if (policy_info[i]->value != (char *) NULL)
685           (void) FormatLocaleFile(file,"    value: %s\n",policy_info[i]->value);
686       }
687     else
688       {
689         (void) FormatLocaleFile(file,"    rights: ");
690         if (policy_info[i]->rights == NoPolicyRights)
691           (void) FormatLocaleFile(file,"None ");
692         if ((policy_info[i]->rights & ReadPolicyRights) != 0)
693           (void) FormatLocaleFile(file,"Read ");
694         if ((policy_info[i]->rights & WritePolicyRights) != 0)
695           (void) FormatLocaleFile(file,"Write ");
696         if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
697           (void) FormatLocaleFile(file,"Execute ");
698         (void) FormatLocaleFile(file,"\n");
699         if (policy_info[i]->pattern != (char *) NULL)
700           (void) FormatLocaleFile(file,"    pattern: %s\n",
701             policy_info[i]->pattern);
702       }
703   }
704   policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
705     policy_info);
706   (void) fflush(file);
707   return(MagickTrue);
708 }
709 
710 /*
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712 %                                                                             %
713 %                                                                             %
714 %                                                                             %
715 +   L o a d P o l i c y C a c h e                                             %
716 %                                                                             %
717 %                                                                             %
718 %                                                                             %
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720 %
721 %  LoadPolicyCache() loads the policy configurations which provides a mapping
722 %  between policy attributes and a policy domain.
723 %
724 %  The format of the LoadPolicyCache method is:
725 %
726 %      MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
727 %        const char *filename,const size_t depth,ExceptionInfo *exception)
728 %
729 %  A description of each parameter follows:
730 %
731 %    o xml:  The policy list in XML format.
732 %
733 %    o filename:  The policy list filename.
734 %
735 %    o depth: depth of <include /> statements.
736 %
737 %    o exception: return any errors or warnings in this structure.
738 %
739 */
LoadPolicyCache(LinkedListInfo * cache,const char * xml,const char * filename,const size_t depth,ExceptionInfo * exception)740 static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
741   const char *filename,const size_t depth,ExceptionInfo *exception)
742 {
743   char
744     keyword[MagickPathExtent],
745     *token;
746 
747   const char
748     *q;
749 
750   MagickStatusType
751     status;
752 
753   PolicyInfo
754     *policy_info;
755 
756   size_t
757     extent;
758 
759   /*
760     Load the policy map file.
761   */
762   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
763     "Loading policy file \"%s\" ...",filename);
764   if (xml == (char *) NULL)
765     return(MagickFalse);
766   status=MagickTrue;
767   policy_info=(PolicyInfo *) NULL;
768   token=AcquireString(xml);
769   extent=strlen(token)+MagickPathExtent;
770   for (q=(const char *) xml; *q != '\0'; )
771   {
772     /*
773       Interpret XML.
774     */
775     GetNextToken(q,&q,extent,token);
776     if (*token == '\0')
777       break;
778     (void) CopyMagickString(keyword,token,MagickPathExtent);
779     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
780       {
781         /*
782           Docdomain element.
783         */
784         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
785           GetNextToken(q,&q,extent,token);
786         continue;
787       }
788     if (LocaleNCompare(keyword,"<!--",4) == 0)
789       {
790         /*
791           Comment element.
792         */
793         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
794           GetNextToken(q,&q,extent,token);
795         continue;
796       }
797     if (LocaleCompare(keyword,"<include") == 0)
798       {
799         /*
800           Include element.
801         */
802         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
803         {
804           (void) CopyMagickString(keyword,token,MagickPathExtent);
805           GetNextToken(q,&q,extent,token);
806           if (*token != '=')
807             continue;
808           GetNextToken(q,&q,extent,token);
809           if (LocaleCompare(keyword,"file") == 0)
810             {
811               if (depth > 200)
812                 (void) ThrowMagickException(exception,GetMagickModule(),
813                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
814               else
815                 {
816                   char
817                     path[MagickPathExtent],
818                     *file_xml;
819 
820                   GetPathComponent(filename,HeadPath,path);
821                   if (*path != '\0')
822                     (void) ConcatenateMagickString(path,DirectorySeparator,
823                       MagickPathExtent);
824                   if (*token == *DirectorySeparator)
825                     (void) CopyMagickString(path,token,MagickPathExtent);
826                   else
827                     (void) ConcatenateMagickString(path,token,MagickPathExtent);
828                   file_xml=FileToXML(path,~0UL);
829                   if (file_xml != (char *) NULL)
830                     {
831                       status&=LoadPolicyCache(cache,file_xml,path,
832                         depth+1,exception);
833                       file_xml=DestroyString(file_xml);
834                     }
835                 }
836             }
837         }
838         continue;
839       }
840     if (LocaleCompare(keyword,"<policy") == 0)
841       {
842         /*
843           Policy element.
844         */
845         policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
846         if (policy_info == (PolicyInfo *) NULL)
847           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
848         (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
849         policy_info->path=ConstantString(filename);
850         policy_info->exempt=MagickFalse;
851         policy_info->signature=MagickCoreSignature;
852         continue;
853       }
854     if (policy_info == (PolicyInfo *) NULL)
855       continue;
856     if (LocaleCompare(keyword,"/>") == 0)
857       {
858         status=AppendValueToLinkedList(cache,policy_info);
859         if (status == MagickFalse)
860           (void) ThrowMagickException(exception,GetMagickModule(),
861             ResourceLimitError,"MemoryAllocationFailed","`%s'",
862             policy_info->name);
863         policy_info=(PolicyInfo *) NULL;
864         continue;
865       }
866     GetNextToken(q,(const char **) NULL,extent,token);
867     if (*token != '=')
868       continue;
869     GetNextToken(q,&q,extent,token);
870     GetNextToken(q,&q,extent,token);
871     switch (*keyword)
872     {
873       case 'D':
874       case 'd':
875       {
876         if (LocaleCompare((char *) keyword,"domain") == 0)
877           {
878             policy_info->domain=(PolicyDomain) ParseCommandOption(
879               MagickPolicyDomainOptions,MagickTrue,token);
880             break;
881           }
882         break;
883       }
884       case 'N':
885       case 'n':
886       {
887         if (LocaleCompare((char *) keyword,"name") == 0)
888           {
889             policy_info->name=ConstantString(token);
890             break;
891           }
892         break;
893       }
894       case 'P':
895       case 'p':
896       {
897         if (LocaleCompare((char *) keyword,"pattern") == 0)
898           {
899             policy_info->pattern=ConstantString(token);
900             break;
901           }
902         break;
903       }
904       case 'R':
905       case 'r':
906       {
907         if (LocaleCompare((char *) keyword,"rights") == 0)
908           {
909             policy_info->rights=(PolicyRights) ParseCommandOption(
910               MagickPolicyRightsOptions,MagickTrue,token);
911             break;
912           }
913         break;
914       }
915       case 'S':
916       case 's':
917       {
918         if (LocaleCompare((char *) keyword,"stealth") == 0)
919           {
920             policy_info->stealth=IsStringTrue(token);
921             break;
922           }
923         break;
924       }
925       case 'V':
926       case 'v':
927       {
928         if (LocaleCompare((char *) keyword,"value") == 0)
929           {
930             policy_info->value=ConstantString(token);
931             break;
932           }
933         break;
934       }
935       default:
936         break;
937     }
938   }
939   token=(char *) RelinquishMagickMemory(token);
940   return(status != 0 ? MagickTrue : MagickFalse);
941 }
942 
943 /*
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 %                                                                             %
946 %                                                                             %
947 %                                                                             %
948 +   P o l i c y C o m p o n e n t G e n e s i s                               %
949 %                                                                             %
950 %                                                                             %
951 %                                                                             %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %
954 %  PolicyComponentGenesis() instantiates the policy component.
955 %
956 %  The format of the PolicyComponentGenesis method is:
957 %
958 %      MagickBooleanType PolicyComponentGenesis(void)
959 %
960 */
PolicyComponentGenesis(void)961 MagickPrivate MagickBooleanType PolicyComponentGenesis(void)
962 {
963   if (policy_semaphore == (SemaphoreInfo *) NULL)
964     policy_semaphore=AcquireSemaphoreInfo();
965   return(MagickTrue);
966 }
967 
968 /*
969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970 %                                                                             %
971 %                                                                             %
972 %                                                                             %
973 +   P o l i c y C o m p o n e n t T e r m i n u s                             %
974 %                                                                             %
975 %                                                                             %
976 %                                                                             %
977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 %
979 %  PolicyComponentTerminus() destroys the policy component.
980 %
981 %  The format of the PolicyComponentTerminus method is:
982 %
983 %      PolicyComponentTerminus(void)
984 %
985 */
986 
DestroyPolicyElement(void * policy_info)987 static void *DestroyPolicyElement(void *policy_info)
988 {
989   register PolicyInfo
990     *p;
991 
992   p=(PolicyInfo *) policy_info;
993   if (p->exempt == MagickFalse)
994     {
995       if (p->value != (char *) NULL)
996         p->value=DestroyString(p->value);
997       if (p->pattern != (char *) NULL)
998         p->pattern=DestroyString(p->pattern);
999       if (p->name != (char *) NULL)
1000         p->name=DestroyString(p->name);
1001       if (p->path != (char *) NULL)
1002         p->path=DestroyString(p->path);
1003     }
1004   p=(PolicyInfo *) RelinquishMagickMemory(p);
1005   return((void *) NULL);
1006 }
1007 
PolicyComponentTerminus(void)1008 MagickPrivate void PolicyComponentTerminus(void)
1009 {
1010   if (policy_semaphore == (SemaphoreInfo *) NULL)
1011     ActivateSemaphoreInfo(&policy_semaphore);
1012   LockSemaphoreInfo(policy_semaphore);
1013   if (policy_cache != (LinkedListInfo *) NULL)
1014     policy_cache=DestroyLinkedList(policy_cache,DestroyPolicyElement);
1015   UnlockSemaphoreInfo(policy_semaphore);
1016   RelinquishSemaphoreInfo(&policy_semaphore);
1017 }
1018