MagickCore  6.9.13-49
Convert, Edit, Or Compose Bitmap Images
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 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://imagemagick.org/license/ %
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 */
36 ␌
37 /*
38  Include declarations.
39 */
40 #include "magick/studio.h"
41 #include "magick/cache-private.h"
42 #include "magick/client.h"
43 #include "magick/configure.h"
44 #include "magick/exception.h"
45 #include "magick/exception-private.h"
46 #include "magick/hashmap-private.h"
47 #include "magick/locale_.h"
48 #include "magick/magick-private.h"
49 #include "magick/memory_.h"
50 #include "magick/memory-private.h"
51 #include "magick/monitor.h"
52 #include "magick/monitor-private.h"
53 #include "magick/option.h"
54 #include "magick/policy.h"
55 #include "magick/policy-private.h"
56 #include "magick/resource_.h"
57 #include "magick/semaphore.h"
58 #include "magick/stream-private.h"
59 #include "magick/string_.h"
60 #include "magick/string-private.h"
61 #include "magick/timer-private.h"
62 #include "magick/token.h"
63 #include "magick/utility.h"
64 #include "magick/utility-private.h"
65 #include "magick/xml-tree.h"
66 #include "magick/xml-tree-private.h"
67 #if defined(MAGICKCORE_XML_DELEGATE)
68 # include <libxml/parser.h>
69 # include <libxml/tree.h>
70 #endif
71 ␌
72 /*
73  Define declarations.
74 */
75 #define PolicyFilename "policy.xml"
76 ␌
77 /*
78  Typedef declarations.
79 */
81 {
82  char
83  *path;
84 
85  PolicyDomain
86  domain;
87 
88  PolicyRights
89  rights;
90 
91  char
92  *name,
93  *pattern,
94  *value;
95 
96  MagickBooleanType
97  exempt,
98  stealth,
99  debug;
100 
102  *semaphore;
103 
104  size_t
105  signature;
106 };
107 
108 typedef struct _PolicyMapInfo
109 {
110  const PolicyDomain
111  domain;
112 
113  const PolicyRights
114  rights;
115 
116  const char
117  *name,
118  *pattern,
119  *value;
120 } PolicyMapInfo;
121 ␌
122 /*
123  Static declarations.
124 */
125 static const PolicyMapInfo
126  PolicyMap[] =
127  {
128  { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
129  (const char *) NULL, (const char *) NULL }
130  };
131 
132 static LinkedListInfo
133  *policy_cache = (LinkedListInfo *) NULL;
134 
135 static SemaphoreInfo
136  *policy_semaphore = (SemaphoreInfo *) NULL;
137 ␌
138 /*
139  Forward declarations.
140 */
141 static MagickBooleanType
142  IsPolicyCacheInstantiated(ExceptionInfo *),
143  LoadPolicyCache(LinkedListInfo *,const char *,const char *,const size_t,
144  ExceptionInfo *),
145  SetMagickSecurityPolicyValue(const PolicyDomain,const char *,const char *,
146  ExceptionInfo *);
147 ␌
148 /*
149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 % %
151 % %
152 % %
153 % A c q u i r e P o l i c y C a c h e %
154 % %
155 % %
156 % %
157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 %
159 % AcquirePolicyCache() caches one or more policy configurations which provides
160 % a mapping between policy attributes and a policy name.
161 %
162 % The format of the AcquirePolicyCache method is:
163 %
164 % LinkedListInfo *AcquirePolicyCache(const char *filename,
165 % ExceptionInfo *exception)
166 %
167 % A description of each parameter follows:
168 %
169 % o filename: the policy configuration file name.
170 %
171 % o exception: return any errors or warnings in this structure.
172 %
173 */
174 static LinkedListInfo *AcquirePolicyCache(const char *filename,
175  ExceptionInfo *exception)
176 {
178  *cache;
179 
180  MagickStatusType
181  status;
182 
183  ssize_t
184  i;
185 
186  /*
187  Load external policy map.
188  */
189  cache=NewLinkedList(0);
190  if (cache == (LinkedListInfo *) NULL)
191  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
192  status=MagickTrue;
193 #if MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
194  magick_unreferenced(filename);
195  status=LoadPolicyCache(cache,ZeroConfigurationPolicy,"[zero-configuration]",0,
196  exception);
197  if (status == MagickFalse)
198  CatchException(exception);
199 #else
200  {
201  const StringInfo
202  *option;
203 
205  *options;
206 
207  options=GetConfigureOptions(filename,exception);
208  option=(const StringInfo *) GetNextValueInLinkedList(options);
209  while (option != (const StringInfo *) NULL)
210  {
211  status&=LoadPolicyCache(cache,(const char *) GetStringInfoDatum(option),
212  GetStringInfoPath(option),0,exception);
213  if (status == MagickFalse)
214  CatchException(exception);
215  option=(const StringInfo *) GetNextValueInLinkedList(options);
216  }
217  options=DestroyConfigureOptions(options);
218  }
219 #endif
220  /*
221  Load built-in policy map.
222  */
223  for (i=0; i < (ssize_t) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
224  {
225  const PolicyMapInfo
226  *p;
227 
228  PolicyInfo
229  *policy_info;
230 
231  p=PolicyMap+i;
232  policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
233  if (policy_info == (PolicyInfo *) NULL)
234  {
235  (void) ThrowMagickException(exception,GetMagickModule(),
236  ResourceLimitError,"MemoryAllocationFailed","`%s'",
237  p->name == (char *) NULL ? "" : p->name);
238  CatchException(exception);
239  status=MagickFalse;
240  continue;
241  }
242  (void) memset(policy_info,0,sizeof(*policy_info));
243  policy_info->path=(char *) "[built-in]";
244  policy_info->domain=p->domain;
245  policy_info->rights=p->rights;
246  policy_info->name=(char *) p->name;
247  policy_info->pattern=(char *) p->pattern;
248  policy_info->value=(char *) p->value;
249  policy_info->exempt=MagickTrue;
250  policy_info->signature=MagickCoreSignature;
251  status&=AppendValueToLinkedList(cache,policy_info);
252  if (status == MagickFalse)
253  {
254  (void) ThrowMagickException(exception,GetMagickModule(),
255  ResourceLimitError,"MemoryAllocationFailed","`%s'",
256  p->name == (char *) NULL ? "" : p->name);
257  CatchException(exception);
258  }
259  }
260  if (status == MagickFalse)
261  CatchException(exception);
262  return(cache);
263 }
264 ␌
265 /*
266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 % %
268 % %
269 % %
270 + G e t P o l i c y I n f o %
271 % %
272 % %
273 % %
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 %
276 % GetPolicyInfo() searches the policy list for the specified name and if found
277 % returns attributes for that policy.
278 %
279 % The format of the GetPolicyInfo method is:
280 %
281 % PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
282 %
283 % A description of each parameter follows:
284 %
285 % o name: the policy name.
286 %
287 % o exception: return any errors or warnings in this structure.
288 %
289 */
290 static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
291 {
292  char
293  policyname[MagickPathExtent],
294  *q;
295 
297  *p;
298 
299  PolicyDomain
300  domain;
301 
302  PolicyInfo
303  *policy;
304 
305  assert(exception != (ExceptionInfo *) NULL);
306  if (IsPolicyCacheInstantiated(exception) == MagickFalse)
307  return((PolicyInfo *) NULL);
308  /*
309  Strip names of whitespace.
310  */
311  *policyname='\0';
312  if (name != (const char *) NULL)
313  (void) CopyMagickString(policyname,name,MagickPathExtent);
314  for (q=policyname; *q != '\0'; q++)
315  {
316  if (isspace((int) ((unsigned char) *q)) == 0)
317  continue;
318  (void) CopyMagickString(q,q+1,MagickPathExtent);
319  q--;
320  }
321  /*
322  Strip domain from policy name (e.g. resource:map).
323  */
324  domain=UndefinedPolicyDomain;
325  for (q=policyname; *q != '\0'; q++)
326  {
327  if (*q != ':')
328  continue;
329  *q='\0';
330  domain=(PolicyDomain) ParseCommandOption(MagickPolicyDomainOptions,
331  MagickTrue,policyname);
332  (void) CopyMagickString(policyname,q+1,MagickPathExtent);
333  break;
334  }
335  /*
336  Search for policy tag.
337  */
338  policy=(PolicyInfo *) NULL;
339  LockSemaphoreInfo(policy_semaphore);
340  ResetLinkedListIterator(policy_cache);
341  p=GetHeadElementInLinkedList(policy_cache);
342  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
343  {
344  UnlockSemaphoreInfo(policy_semaphore);
345  if (p != (ElementInfo *) NULL)
346  policy=(PolicyInfo *) p->value;
347  return(policy);
348  }
349  while (p != (ElementInfo *) NULL)
350  {
351  policy=(PolicyInfo *) p->value;
352  if ((domain == UndefinedPolicyDomain) || (policy->domain == domain))
353  if (LocaleCompare(policyname,policy->name) == 0)
354  break;
355  p=p->next;
356  }
357  if (p == (ElementInfo *) NULL)
358  policy=(PolicyInfo *) NULL;
359  else
360  (void) SetHeadElementInLinkedList(policy_cache,p);
361  UnlockSemaphoreInfo(policy_semaphore);
362  return(policy);
363 }
364 ␌
365 /*
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % %
368 % %
369 % %
370 % G e t P o l i c y I n f o L i s t %
371 % %
372 % %
373 % %
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 %
376 % GetPolicyInfoList() returns any policies that match the specified pattern.
377 %
378 % The format of the GetPolicyInfoList function is:
379 %
380 % const PolicyInfo **GetPolicyInfoList(const char *pattern,
381 % size_t *number_policies,ExceptionInfo *exception)
382 %
383 % A description of each parameter follows:
384 %
385 % o pattern: Specifies a pointer to a text string containing a pattern.
386 %
387 % o number_policies: returns the number of policies in the list.
388 %
389 % o exception: return any errors or warnings in this structure.
390 %
391 */
392 MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
393  size_t *number_policies,ExceptionInfo *exception)
394 {
395  const PolicyInfo
396  **policies;
397 
398  const PolicyInfo
399  *p;
400 
401  ssize_t
402  i;
403 
404  /*
405  Allocate policy list.
406  */
407  assert(pattern != (char *) NULL);
408  assert(number_policies != (size_t *) NULL);
409  if (IsEventLogging() != MagickFalse)
410  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
411  *number_policies=0;
412  p=GetPolicyInfo("*",exception);
413  if (p == (const PolicyInfo *) NULL)
414  return((const PolicyInfo **) NULL);
415  policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
416  GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
417  if (policies == (const PolicyInfo **) NULL)
418  return((const PolicyInfo **) NULL);
419  /*
420  Generate policy list.
421  */
422  LockSemaphoreInfo(policy_semaphore);
423  ResetLinkedListIterator(policy_cache);
424  p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
425  for (i=0; p != (const PolicyInfo *) NULL; )
426  {
427  if ((p->stealth == MagickFalse) &&
428  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
429  policies[i++]=p;
430  p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
431  }
432  UnlockSemaphoreInfo(policy_semaphore);
433  policies[i]=(PolicyInfo *) NULL;
434  *number_policies=(size_t) i;
435  return(policies);
436 }
437 ␌
438 /*
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440 % %
441 % %
442 % %
443 % G e t P o l i c y L i s t %
444 % %
445 % %
446 % %
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 %
449 % GetPolicyList() returns any policies that match the specified pattern.
450 %
451 % The format of the GetPolicyList function is:
452 %
453 % char **GetPolicyList(const char *pattern,size_t *number_policies,
454 % ExceptionInfo *exception)
455 %
456 % A description of each parameter follows:
457 %
458 % o pattern: a pointer to a text string containing a pattern.
459 %
460 % o number_policies: returns the number of policies in the list.
461 %
462 % o exception: return any errors or warnings in this structure.
463 %
464 */
465 
466 static char *AcquirePolicyString(const char *source,const size_t pad)
467 {
468  char
469  *destination;
470 
471  size_t
472  length;
473 
474  length=0;
475  if (source != (char *) NULL)
476  length+=strlen(source);
477  destination=(char *) NULL;
478  if (~length >= pad)
479  destination=(char *) AcquireMagickMemory((length+pad)*sizeof(*destination));
480  if (destination == (char *) NULL)
481  ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
482  if (source != (char *) NULL)
483  (void) memcpy(destination,source,length*sizeof(*destination));
484  destination[length]='\0';
485  return(destination);
486 }
487 
488 MagickExport char **GetPolicyList(const char *pattern,size_t *number_policies,
489  ExceptionInfo *exception)
490 {
491  char
492  **policies;
493 
494  const PolicyInfo
495  *p;
496 
497  ssize_t
498  i;
499 
500  /*
501  Allocate policy list.
502  */
503  assert(pattern != (char *) NULL);
504  assert(number_policies != (size_t *) NULL);
505  if (IsEventLogging() != MagickFalse)
506  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
507  *number_policies=0;
508  p=GetPolicyInfo("*",exception);
509  if (p == (const PolicyInfo *) NULL)
510  return((char **) NULL);
511  policies=(char **) AcquireQuantumMemory((size_t)
512  GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
513  if (policies == (char **) NULL)
514  return((char **) NULL);
515  /*
516  Generate policy list.
517  */
518  LockSemaphoreInfo(policy_semaphore);
519  ResetLinkedListIterator(policy_cache);
520  p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
521  for (i=0; p != (const PolicyInfo *) NULL; )
522  {
523  if ((p->stealth == MagickFalse) &&
524  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
525  policies[i++]=AcquirePolicyString(p->name,1);
526  p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
527  }
528  UnlockSemaphoreInfo(policy_semaphore);
529  policies[i]=(char *) NULL;
530  *number_policies=(size_t) i;
531  return(policies);
532 }
533 ␌
534 /*
535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536 % %
537 % %
538 % %
539 % G e t P o l i c y V a l u e %
540 % %
541 % %
542 % %
543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 %
545 % GetPolicyValue() returns the value associated with the named policy.
546 %
547 % The format of the GetPolicyValue method is:
548 %
549 % char *GetPolicyValue(const char *name)
550 %
551 % A description of each parameter follows:
552 %
553 % o policy_info: The policy info.
554 %
555 */
556 MagickExport char *GetPolicyValue(const char *name)
557 {
558  const char
559  *value;
560 
561  const PolicyInfo
562  *policy_info;
563 
565  *exception;
566 
567  assert(name != (const char *) NULL);
568  if (IsEventLogging() != MagickFalse)
569  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
570  exception=AcquireExceptionInfo();
571  policy_info=GetPolicyInfo(name,exception);
572  exception=DestroyExceptionInfo(exception);
573  if (policy_info == (PolicyInfo *) NULL)
574  return((char *) NULL);
575  value=policy_info->value;
576  if ((value == (const char *) NULL) || (*value == '\0'))
577  return((char *) NULL);
578  return(AcquirePolicyString(value,1));
579 }
580 ␌
581 /*
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 % %
584 % %
585 % %
586 + 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 %
587 % %
588 % %
589 % %
590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 %
592 % IsPolicyCacheInstantiated() determines if the policy list is instantiated.
593 % If not, it instantiates the list and returns it.
594 %
595 % The format of the IsPolicyInstantiated method is:
596 %
597 % MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
598 %
599 % A description of each parameter follows.
600 %
601 % o exception: return any errors or warnings in this structure.
602 %
603 */
604 static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
605 {
606  if (policy_cache == (LinkedListInfo *) NULL)
607  {
608  (void) GetMaxMemoryRequest(); /* avoid OMP deadlock */
609  if (policy_semaphore == (SemaphoreInfo *) NULL)
610  ActivateSemaphoreInfo(&policy_semaphore);
611  LockSemaphoreInfo(policy_semaphore);
612  if (policy_cache == (LinkedListInfo *) NULL)
613  policy_cache=AcquirePolicyCache(PolicyFilename,exception);
614  UnlockSemaphoreInfo(policy_semaphore);
615  }
616  return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
617 }
618 ␌
619 /*
620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621 % %
622 % %
623 % %
624 % I s R i g h t s A u t h o r i z e d %
625 % %
626 % %
627 % %
628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629 %
630 % IsRightsAuthorized() returns MagickTrue if the policy authorizes the
631 % requested rights for the specified domain.
632 %
633 % Policy evaluation uses a “last match wins” model. Be careful when adding
634 % new rules: any later policy can override earlier denies or allows. Place
635 % broad deny rules first, followed by specific exceptions, and review
636 % ordering to avoid accidental authorization.
637 %
638 % The format of the IsRightsAuthorized method is:
639 %
640 % MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
641 % const PolicyRights rights,const char *pattern)
642 %
643 % A description of each parameter follows:
644 %
645 % o domain: the policy domain.
646 %
647 % o rights: the policy rights.
648 %
649 % o pattern: the pattern.
650 %
651 */
652 
653 MagickPrivate MagickBooleanType IsRightsAuthorizedByName(
654  const PolicyDomain domain,const char *name,const PolicyRights rights,
655  const char *pattern)
656 {
657  char
658  *canonical_directory = (char *) NULL,
659  *canonical_path = (char *) NULL,
660  *canonical_candidate = (char *) NULL,
661  directory[MagickPathExtent],
662  filename[MagickPathExtent];
663 
665  *p;
666 
668  *exception;
669 
670  MagickBooleanType
671  matched_any = MagickFalse,
672  paths_provisioned = MagickFalse,
673  status;
674 
675  PolicyRights
676  effective_rights = AllPolicyRights; /* rights authorized unless denied */
677 
678  /*
679  Load policies.
680  */
681  if ((GetLogEventMask() & PolicyEvent) != 0)
682  (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
683  "Domain: %s; name: %s; rights=%s; pattern=\"%s\"; ...",
684  CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
685  name == (const char *) NULL ? "undefined" : name,
686  CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),
687  pattern == (const char *) NULL ? "undefined" : pattern);
688  exception=AcquireExceptionInfo();
689  status=IsPolicyCacheInstantiated(exception);
690  exception=DestroyExceptionInfo(exception);
691  if (status == MagickFalse)
692  {
693  if ((GetLogEventMask() & PolicyEvent) != 0)
694  (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
695  " authorized: true (no security policies found)");
696  return(MagickTrue);
697  }
698  /*
699  Evaluate policies in order; last match wins.
700  */
701  LockSemaphoreInfo(policy_semaphore);
702  ResetLinkedListIterator(policy_cache);
703  p=GetHeadElementInLinkedList(policy_cache);
704  for ( ; p != (ElementInfo *) NULL; p=p->next)
705  {
706  const PolicyInfo
707  *policy = (PolicyInfo *) p->value;
708 
709  MagickBooleanType
710  match = MagickFalse;
711 
712  if (policy->domain != domain)
713  continue;
714  if ((name != (char *) NULL) && (LocaleCompare(name,policy->name) != 0))
715  continue;
716  match=GlobExpression(pattern,policy->pattern,MagickFalse);
717  if (policy->domain == PathPolicyDomain)
718  {
719  if (paths_provisioned == MagickFalse)
720  {
721  /*
722  Generate directory, basename, and canonical path.
723  */
724  paths_provisioned=MagickTrue;
725  GetPathComponent(pattern,HeadPath,directory);
726  GetPathComponent(pattern,TailPath,filename);
727  canonical_directory=realpath_utf8(directory);
728  if ((canonical_directory != (char *) NULL) && (*filename != '\0'))
729  {
730  size_t
731  length;
732 
733  length=strlen(canonical_directory)+strlen(filename)+2;
734  canonical_candidate=(char *) AcquireCriticalMemory(length*
735  sizeof(*canonical_candidate));
736  if (canonical_candidate != (char *) NULL)
737  (void) FormatLocaleString(canonical_candidate,length,"%s%s%s",
738  canonical_directory,DirectorySeparator,filename);
739  }
740  canonical_path=realpath_utf8(pattern);
741  }
742  /*
743  Match against directory, basename, and canonical path.
744  */
745  if ((canonical_directory != (char *) NULL) && (match == MagickFalse))
746  match=GlobExpression(canonical_directory,policy->pattern,MagickFalse);
747  if ((canonical_candidate != (char *) NULL) && (match == MagickFalse))
748  match=GlobExpression(canonical_candidate,policy->pattern,MagickFalse);
749  if ((canonical_path != (char *) NULL) && (match == MagickFalse))
750  match=GlobExpression(canonical_path,policy->pattern,MagickFalse);
751  }
752  if (match == MagickFalse)
753  continue;
754  matched_any=MagickTrue;
755  effective_rights=policy->rights;
756  }
757  UnlockSemaphoreInfo(policy_semaphore);
758  if (canonical_directory != (char *) NULL)
759  canonical_directory=DestroyString(canonical_directory);
760  if (canonical_candidate != (char *) NULL)
761  canonical_candidate=DestroyString(canonical_candidate);
762  if (canonical_path != (char *) NULL)
763  canonical_path=DestroyString(canonical_path);
764  /*
765  Is rights authorized?
766  */
767  status=MagickTrue;
768  if (matched_any != MagickFalse)
769  {
770  if (((rights & ReadPolicyRights) != 0) &&
771  ((effective_rights & ReadPolicyRights) == 0))
772  status=MagickFalse;
773  if (((rights & WritePolicyRights) != 0) &&
774  ((effective_rights & WritePolicyRights) == 0))
775  status=MagickFalse;
776  if (((rights & ExecutePolicyRights) != 0) &&
777  ((effective_rights & ExecutePolicyRights) == 0))
778  status=MagickFalse;
779  }
780  if ((GetLogEventMask() & PolicyEvent) != 0)
781  (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
782  " authorized: %s",status == MagickFalse ? "false" : "true");
783  return(status);
784 }
785 
786 MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
787  const PolicyRights rights,const char *pattern)
788 {
789  return(IsRightsAuthorizedByName(domain,(const char *) NULL,rights,pattern));
790 }
791 ␌
792 /*
793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
794 % %
795 % %
796 % %
797 % L i s t P o l i c y I n f o %
798 % %
799 % %
800 % %
801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802 %
803 % ListPolicyInfo() lists policies to the specified file.
804 %
805 % The format of the ListPolicyInfo method is:
806 %
807 % MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
808 %
809 % A description of each parameter follows.
810 %
811 % o file: List policy names to this file handle.
812 %
813 % o exception: return any errors or warnings in this structure.
814 %
815 */
816 MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
817  ExceptionInfo *exception)
818 {
819  const char
820  *path,
821  *domain;
822 
823  const PolicyInfo
824  **policy_info;
825 
826  ssize_t
827  i;
828 
829  size_t
830  number_policies;
831 
832  /*
833  List name and attributes of each policy in the list.
834  */
835  if (file == (const FILE *) NULL)
836  file=stdout;
837  policy_info=GetPolicyInfoList("*",&number_policies,exception);
838  if (policy_info == (const PolicyInfo **) NULL)
839  return(MagickFalse);
840  path=(const char *) NULL;
841  for (i=0; i < (ssize_t) number_policies; i++)
842  {
843  if (policy_info[i]->stealth != MagickFalse)
844  continue;
845  if (((path == (const char *) NULL) ||
846  (LocaleCompare(path,policy_info[i]->path) != 0)) &&
847  (policy_info[i]->path != (char *) NULL))
848  (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
849  path=policy_info[i]->path;
850  domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
851  policy_info[i]->domain);
852  (void) FormatLocaleFile(file," Policy: %s\n",domain);
853  if ((policy_info[i]->domain == CachePolicyDomain) ||
854  (policy_info[i]->domain == ResourcePolicyDomain) ||
855  (policy_info[i]->domain == SystemPolicyDomain))
856  {
857  if (policy_info[i]->name != (char *) NULL)
858  (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
859  if (policy_info[i]->value != (char *) NULL)
860  (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
861  }
862  else
863  {
864  (void) FormatLocaleFile(file," rights: ");
865  if (policy_info[i]->rights == NoPolicyRights)
866  (void) FormatLocaleFile(file,"None ");
867  if ((policy_info[i]->rights & ReadPolicyRights) != 0)
868  (void) FormatLocaleFile(file,"Read ");
869  if ((policy_info[i]->rights & WritePolicyRights) != 0)
870  (void) FormatLocaleFile(file,"Write ");
871  if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
872  (void) FormatLocaleFile(file,"Execute ");
873  (void) FormatLocaleFile(file,"\n");
874  if (policy_info[i]->pattern != (char *) NULL)
875  (void) FormatLocaleFile(file," pattern: %s\n",
876  policy_info[i]->pattern);
877  }
878  }
879  policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
880  policy_info);
881  (void) fflush(file);
882  return(MagickTrue);
883 }
884 ␌
885 /*
886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887 % %
888 % %
889 % %
890 + L o a d P o l i c y C a c h e %
891 % %
892 % %
893 % %
894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895 %
896 % LoadPolicyCache() loads the policy configurations which provides a mapping
897 % between policy attributes and a policy domain.
898 %
899 % The format of the LoadPolicyCache method is:
900 %
901 % MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
902 % const char *filename,const size_t depth,ExceptionInfo *exception)
903 %
904 % A description of each parameter follows:
905 %
906 % o xml: The policy list in XML format.
907 %
908 % o filename: The policy list filename.
909 %
910 % o depth: depth of <include /> statements.
911 %
912 % o exception: return any errors or warnings in this structure.
913 %
914 */
915 static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
916  const char *filename,const size_t depth,ExceptionInfo *exception)
917 {
918  char
919  keyword[MagickPathExtent],
920  *token;
921 
922  const char
923  *q;
924 
925  MagickStatusType
926  status;
927 
928  PolicyInfo
929  *policy_info;
930 
931  size_t
932  extent;
933 
934  /*
935  Load the policy map file.
936  */
937  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
938  "Loading policy file \"%s\" ...",filename);
939  if (xml == (char *) NULL)
940  return(MagickFalse);
941  status=MagickTrue;
942  policy_info=(PolicyInfo *) NULL;
943  token=AcquirePolicyString(xml,MagickPathExtent);
944  extent=strlen(token)+MagickPathExtent;
945  for (q=(const char *) xml; *q != '\0'; )
946  {
947  /*
948  Interpret XML.
949  */
950  (void) GetNextToken(q,&q,extent,token);
951  if (*token == '\0')
952  break;
953  (void) CopyMagickString(keyword,token,MagickPathExtent);
954  if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
955  {
956  /*
957  Docdomain element.
958  */
959  while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
960  (void) GetNextToken(q,&q,extent,token);
961  continue;
962  }
963  if (LocaleNCompare(keyword,"<!--",4) == 0)
964  {
965  /*
966  Comment element.
967  */
968  while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
969  (void) GetNextToken(q,&q,extent,token);
970  continue;
971  }
972  if (LocaleCompare(keyword,"<include") == 0)
973  {
974  /*
975  Include element.
976  */
977  while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
978  {
979  (void) CopyMagickString(keyword,token,MagickPathExtent);
980  (void) GetNextToken(q,&q,extent,token);
981  if (*token != '=')
982  continue;
983  (void) GetNextToken(q,&q,extent,token);
984  if (LocaleCompare(keyword,"file") == 0)
985  {
986  if (depth > MagickMaxRecursionDepth)
987  (void) ThrowMagickException(exception,GetMagickModule(),
988  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
989  else
990  {
991  char
992  path[MagickPathExtent],
993  *xml;
994 
995  GetPathComponent(filename,HeadPath,path);
996  if (*path != '\0')
997  (void) ConcatenateMagickString(path,DirectorySeparator,
998  MagickPathExtent);
999  if (*token == *DirectorySeparator)
1000  (void) CopyMagickString(path,token,MagickPathExtent);
1001  else
1002  (void) ConcatenateMagickString(path,token,MagickPathExtent);
1003  xml=FileToXML(path,~0UL);
1004  if (xml != (char *) NULL)
1005  {
1006  status&=LoadPolicyCache(cache,xml,path,depth+1,
1007  exception);
1008  xml=(char *) RelinquishMagickMemory(xml);
1009  }
1010  }
1011  }
1012  }
1013  continue;
1014  }
1015  if (LocaleCompare(keyword,"<policy") == 0)
1016  {
1017  /*
1018  Policy element.
1019  */
1020  policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
1021  if (policy_info == (PolicyInfo *) NULL)
1022  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1023  (void) memset(policy_info,0,sizeof(*policy_info));
1024  policy_info->path=AcquirePolicyString(filename,1);
1025  policy_info->exempt=MagickFalse;
1026  policy_info->signature=MagickCoreSignature;
1027  continue;
1028  }
1029  if (policy_info == (PolicyInfo *) NULL)
1030  continue;
1031  if ((LocaleCompare(keyword,"/>") == 0) ||
1032  (LocaleCompare(keyword,"</policy>") == 0))
1033  {
1034  status=AppendValueToLinkedList(cache,policy_info);
1035  if (status == MagickFalse)
1036  (void) ThrowMagickException(exception,GetMagickModule(),
1037  ResourceLimitError,"MemoryAllocationFailed","`%s'",
1038  policy_info->name);
1039  policy_info=(PolicyInfo *) NULL;
1040  continue;
1041  }
1042  (void) GetNextToken(q,(const char **) NULL,extent,token);
1043  if (*token != '=')
1044  continue;
1045  (void) GetNextToken(q,&q,extent,token);
1046  (void) GetNextToken(q,&q,extent,token);
1047  switch (*keyword)
1048  {
1049  case 'D':
1050  case 'd':
1051  {
1052  if (LocaleCompare((char *) keyword,"domain") == 0)
1053  {
1054  policy_info->domain=(PolicyDomain) ParseCommandOption(
1055  MagickPolicyDomainOptions,MagickTrue,token);
1056  break;
1057  }
1058  break;
1059  }
1060  case 'N':
1061  case 'n':
1062  {
1063  if (LocaleCompare((char *) keyword,"name") == 0)
1064  {
1065  policy_info->name=AcquirePolicyString(token,1);
1066  break;
1067  }
1068  break;
1069  }
1070  case 'P':
1071  case 'p':
1072  {
1073  if (LocaleCompare((char *) keyword,"pattern") == 0)
1074  {
1075  policy_info->pattern=AcquirePolicyString(token,1);
1076  break;
1077  }
1078  break;
1079  }
1080  case 'R':
1081  case 'r':
1082  {
1083  if (LocaleCompare((char *) keyword,"rights") == 0)
1084  {
1085  policy_info->rights=(PolicyRights) ParseCommandOption(
1086  MagickPolicyRightsOptions,MagickTrue,token);
1087  break;
1088  }
1089  break;
1090  }
1091  case 'S':
1092  case 's':
1093  {
1094  if (LocaleCompare((char *) keyword,"stealth") == 0)
1095  {
1096  policy_info->stealth=IsMagickTrue(token);
1097  break;
1098  }
1099  break;
1100  }
1101  case 'V':
1102  case 'v':
1103  {
1104  if (LocaleCompare((char *) keyword,"value") == 0)
1105  {
1106  policy_info->value=AcquirePolicyString(token,1);
1107  break;
1108  }
1109  break;
1110  }
1111  default:
1112  break;
1113  }
1114  }
1115  token=(char *) RelinquishMagickMemory(token);
1116  if (status == MagickFalse)
1117  CatchException(exception);
1118  return(status != 0 ? MagickTrue : MagickFalse);
1119 }
1120 ␌
1121 /*
1122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1123 % %
1124 % %
1125 % %
1126 + P o l i c y C o m p o n e n t G e n e s i s %
1127 % %
1128 % %
1129 % %
1130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1131 %
1132 % PolicyComponentGenesis() instantiates the policy component.
1133 %
1134 % The format of the PolicyComponentGenesis method is:
1135 %
1136 % MagickBooleanType PolicyComponentGenesis(void)
1137 %
1138 */
1139 MagickExport MagickBooleanType PolicyComponentGenesis(void)
1140 {
1141  if (policy_semaphore == (SemaphoreInfo *) NULL)
1142  policy_semaphore=AllocateSemaphoreInfo();
1143  return(MagickTrue);
1144 }
1145 ␌
1146 /*
1147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1148 % %
1149 % %
1150 % %
1151 + P o l i c y C o m p o n e n t T e r m i n u s %
1152 % %
1153 % %
1154 % %
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156 %
1157 % PolicyComponentTerminus() destroys the policy component.
1158 %
1159 % The format of the PolicyComponentTerminus method is:
1160 %
1161 % PolicyComponentTerminus(void)
1162 %
1163 */
1164 
1165 static void *DestroyPolicyElement(void *policy_info)
1166 {
1167  PolicyInfo
1168  *p;
1169 
1170  p=(PolicyInfo *) policy_info;
1171  if (p->exempt == MagickFalse)
1172  {
1173  if (p->value != (char *) NULL)
1174  p->value=DestroyString(p->value);
1175  if (p->pattern != (char *) NULL)
1176  p->pattern=DestroyString(p->pattern);
1177  if (p->name != (char *) NULL)
1178  p->name=DestroyString(p->name);
1179  if (p->path != (char *) NULL)
1180  p->path=DestroyString(p->path);
1181  }
1182  p=(PolicyInfo *) RelinquishMagickMemory(p);
1183  return((void *) NULL);
1184 }
1185 
1186 MagickExport void PolicyComponentTerminus(void)
1187 {
1188  if (policy_semaphore == (SemaphoreInfo *) NULL)
1189  ActivateSemaphoreInfo(&policy_semaphore);
1190  LockSemaphoreInfo(policy_semaphore);
1191  if (policy_cache != (LinkedListInfo *) NULL)
1192  policy_cache=DestroyLinkedList(policy_cache,DestroyPolicyElement);
1193  UnlockSemaphoreInfo(policy_semaphore);
1194  DestroySemaphoreInfo(&policy_semaphore);
1195 }
1196 ␌
1197 /*
1198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199 % %
1200 % %
1201 % %
1202 % S e t M a g i c k S e c u r i t y P o l i c y %
1203 % %
1204 % %
1205 % %
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 %
1208 % SetMagickSecurityPolicy() sets or restricts the ImageMagick security policy.
1209 % It returns MagickFalse if the policy the policy does not parse.
1210 %
1211 % The format of the SetMagickSecurityPolicy method is:
1212 %
1213 % MagickBooleanType SetMagickSecurityPolicy(const char *policy,
1214 % ExceptionInfo *exception)
1215 %
1216 % A description of each parameter follows:
1217 %
1218 % o policy: the security policy in the XML format.
1219 %
1220 % o exception: return any errors or warnings in this structure.
1221 %
1222 */
1223 
1224 static MagickBooleanType ValidateSecurityPolicy(const char *policy,
1225  const char *url,ExceptionInfo *exception)
1226 {
1227 #if defined(MAGICKCORE_XML_DELEGATE)
1228  xmlDocPtr
1229  document;
1230 
1231  /*
1232  Parse security policy.
1233  */
1234  document=xmlReadMemory(policy,(int) strlen(policy),url,NULL,
1235  XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
1236  if (document == (xmlDocPtr) NULL)
1237  {
1238  (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
1239  "PolicyValidationException","'%s'",url);
1240  return(MagickFalse);
1241  }
1242  xmlFreeDoc(document);
1243 #else
1244  (void) policy;
1245  (void) url;
1246  (void) exception;
1247 #endif
1248  return(MagickTrue);
1249 }
1250 
1251 MagickExport MagickBooleanType SetMagickSecurityPolicy(const char *policy,
1252  ExceptionInfo *exception)
1253 {
1254  MagickBooleanType
1255  status;
1256 
1258  *user_policies;
1259 
1260  PolicyInfo
1261  *p;
1262 
1263  /*
1264  Load user policies.
1265  */
1266  assert(exception != (ExceptionInfo *) NULL);
1267  if (policy == (const char *) NULL)
1268  return(MagickFalse);
1269  if (ValidateSecurityPolicy(policy,PolicyFilename,exception) == MagickFalse)
1270  return(MagickFalse);
1271  status=LoadPolicyCache(policy_cache,policy,"[user-policy]",0,exception);
1272  if (status == MagickFalse)
1273  return(status);
1274  /*
1275  Synchronize user policies.
1276  */
1277  user_policies=NewLinkedList(0);
1278  status=LoadPolicyCache(user_policies,policy,"[user-policy]",0,exception);
1279  if (status == MagickFalse)
1280  {
1281  user_policies=DestroyLinkedList(user_policies,DestroyPolicyElement);
1282  return(MagickFalse);
1283  }
1284  ResetLinkedListIterator(user_policies);
1285  p=(PolicyInfo *) GetNextValueInLinkedList(user_policies);
1286  while (p != (PolicyInfo *) NULL)
1287  {
1288  if ((p->name != (char *) NULL) && (p->value != (char *) NULL))
1289  (void) SetMagickSecurityPolicyValue(p->domain,p->name,p->value,exception);
1290  p=(PolicyInfo *) GetNextValueInLinkedList(user_policies);
1291  }
1292  user_policies=DestroyLinkedList(user_policies,DestroyPolicyElement);
1293  return(status);
1294 }
1295 ␌
1296 /*
1297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1298 % %
1299 % %
1300 % %
1301 % S e t M a g i c k S e c u r i t y P o l i c y V a l u e %
1302 % %
1303 % %
1304 % %
1305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1306 %
1307 % SetMagickSecurityPolicyValue() sets a value associated with an ImageMagick
1308 % security policy. For most policies, the value must be less than any value
1309 % set by the security policy configuration file (i.e. policy.xml). It returns
1310 % MagickFalse if the policy cannot be modified or if the policy does not parse.
1311 %
1312 % The format of the SetMagickSecurityPolicyValue method is:
1313 %
1314 % MagickBooleanType SetMagickSecurityPolicyValue(
1315 % const PolicyDomain domain,const char *name,const char *value,
1316 % ExceptionInfo *exception)
1317 %
1318 % A description of each parameter follows:
1319 %
1320 % o domain: the domain of the policy (e.g. system, resource).
1321 %
1322 % o name: the name of the policy.
1323 %
1324 % o value: the value to set the policy to.
1325 %
1326 % o exception: return any errors or warnings in this structure.
1327 %
1328 */
1329 static MagickBooleanType SetMagickSecurityPolicyValue(const PolicyDomain domain,
1330  const char *name,const char *value,ExceptionInfo *exception)
1331 {
1332  magick_unreferenced(exception);
1333  assert(exception != (ExceptionInfo *) NULL);
1334  if ((name == (const char *) NULL) || (value == (const char *) NULL))
1335  return(MagickFalse);
1336  switch (domain)
1337  {
1338  case CachePolicyDomain:
1339  {
1340  if (LocaleCompare(name,"memory-map") == 0)
1341  {
1342  if (LocaleCompare(value,"anonymous") != 0)
1343  return(MagickFalse);
1344  ResetCacheAnonymousMemory();
1345  ResetStreamAnonymousMemory();
1346  return(MagickTrue);
1347  }
1348  break;
1349  }
1350  case ResourcePolicyDomain:
1351  {
1352  ssize_t
1353  type;
1354 
1355  type=ParseCommandOption(MagickResourceOptions,MagickFalse,name);
1356  if (type >= 0)
1357  {
1358  MagickSizeType
1359  limit;
1360 
1361  limit=MagickResourceInfinity;
1362  if (LocaleCompare("unlimited",value) != 0)
1363  limit=StringToMagickSizeType(value,100.0);
1364  if ((ResourceType) type == TimeResource)
1365  limit=(MagickSizeType) ParseMagickTimeToLive(value);
1366  return(SetMagickResourceLimit((ResourceType) type,limit));
1367  }
1368  break;
1369  }
1370  case SystemPolicyDomain:
1371  {
1372  if (LocaleCompare(name,"max-memory-request") == 0)
1373  {
1374  MagickSizeType
1375  limit;
1376 
1377  limit=MagickResourceInfinity;
1378  if (LocaleCompare("unlimited",value) != 0)
1379  limit=StringToMagickSizeType(value,100.0);
1380  SetMaxMemoryRequest(limit);
1381  return(MagickTrue);
1382  }
1383  if (LocaleCompare(name,"memory-map") == 0)
1384  {
1385  if (LocaleCompare(value,"anonymous") != 0)
1386  return(MagickFalse);
1387  ResetVirtualAnonymousMemory();
1388  return(MagickTrue);
1389  }
1390  if (LocaleCompare(name,"precision") == 0)
1391  {
1392  int
1393  limit;
1394 
1395  limit=StringToInteger(value);
1396  SetMagickPrecision(limit);
1397  return(MagickTrue);
1398  }
1399  break;
1400  }
1401  case CoderPolicyDomain:
1402  case DelegatePolicyDomain:
1403  case FilterPolicyDomain:
1404  case ModulePolicyDomain:
1405  case PathPolicyDomain:
1406  default:
1407  break;
1408  }
1409  return(MagickFalse);
1410 }