2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % PPPP OOO L IIIII CCCC Y Y %
9 % P OOO LLLLL IIIII CCCC Y %
12 % MagickCore Policy Methods %
19 % Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization %
20 % dedicated to making software imaging solutions freely available. %
22 % You may not use this file except in compliance with the License. You may %
23 % obtain a copy of the License at %
25 % https://www.imagemagick.org/script/license.php %
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. %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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).
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/resource-private.h"
56 #include "MagickCore/semaphore.h"
57 #include "MagickCore/string_.h"
58 #include "MagickCore/token.h"
59 #include "MagickCore/utility.h"
60 #include "MagickCore/utility-private.h"
61 #include "MagickCore/xml-tree.h"
62 #include "MagickCore/xml-tree-private.h"
67 #define PolicyFilename "policy.xml"
100 typedef struct _PolicyMapInfo
117 static const PolicyMapInfo
120 { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
121 (const char *) NULL, (const char *) NULL }
124 static LinkedListInfo
125 *policy_cache = (LinkedListInfo *) NULL;
128 *policy_semaphore = (SemaphoreInfo *) NULL;
131 Forward declarations.
133 static MagickBooleanType
134 IsPolicyCacheInstantiated(ExceptionInfo *),
135 LoadPolicyCache(LinkedListInfo *,const char *,const char *,const size_t,
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 % A c q u i r e P o l i c y C a c h e %
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 % AcquirePolicyCache() caches one or more policy configurations which provides
150 % a mapping between policy attributes and a policy name.
152 % The format of the AcquirePolicyCache method is:
154 % LinkedListInfo *AcquirePolicyCache(const char *filename,
155 % ExceptionInfo *exception)
157 % A description of each parameter follows:
159 % o filename: the policy configuration file name.
161 % o exception: return any errors or warnings in this structure.
164 static LinkedListInfo *AcquirePolicyCache(const char *filename,
165 ExceptionInfo *exception)
177 Load external policy map.
179 cache=NewLinkedList(0);
180 if (cache == (LinkedListInfo *) NULL)
181 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
183 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
184 status=LoadPolicyCache(cache,ZeroConfigurationPolicy,"[zero-configuration]",0,
194 options=GetConfigureOptions(filename,exception);
195 option=(const StringInfo *) GetNextValueInLinkedList(options);
196 while (option != (const StringInfo *) NULL)
198 status&=LoadPolicyCache(cache,(const char *) GetStringInfoDatum(option),
199 GetStringInfoPath(option),0,exception);
200 option=(const StringInfo *) GetNextValueInLinkedList(options);
202 options=DestroyConfigureOptions(options);
206 Load built-in policy map.
208 for (i=0; i < (ssize_t) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
213 register const PolicyMapInfo
217 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
218 if (policy_info == (PolicyInfo *) NULL)
220 (void) ThrowMagickException(exception,GetMagickModule(),
221 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
224 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
225 policy_info->path=(char *) "[built-in]";
226 policy_info->domain=p->domain;
227 policy_info->rights=p->rights;
228 policy_info->name=(char *) p->name;
229 policy_info->pattern=(char *) p->pattern;
230 policy_info->value=(char *) p->value;
231 policy_info->exempt=MagickTrue;
232 policy_info->signature=MagickCoreSignature;
233 status&=AppendValueToLinkedList(cache,policy_info);
234 if (status == MagickFalse)
235 (void) ThrowMagickException(exception,GetMagickModule(),
236 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 + G e t P o l i c y I n f o %
250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 % GetPolicyInfo() searches the policy list for the specified name and if found
253 % returns attributes for that policy.
255 % The format of the GetPolicyInfo method is:
257 % PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
259 % A description of each parameter follows:
261 % o name: the policy name.
263 % o exception: return any errors or warnings in this structure.
266 static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
269 policyname[MagickPathExtent];
280 assert(exception != (ExceptionInfo *) NULL);
281 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
282 return((PolicyInfo *) NULL);
284 Strip names of whitespace.
287 if (name != (const char *) NULL)
288 (void) CopyMagickString(policyname,name,MagickPathExtent);
289 for (q=policyname; *q != '\0'; q++)
291 if (isspace((int) ((unsigned char) *q)) == 0)
293 (void) CopyMagickString(q,q+1,MagickPathExtent);
297 Strip domain from policy name (e.g. resource:map).
299 domain=UndefinedPolicyDomain;
300 for (q=policyname; *q != '\0'; q++)
305 domain=(PolicyDomain) ParseCommandOption(MagickPolicyDomainOptions,
306 MagickTrue,policyname);
307 (void) CopyMagickString(policyname,q+1,MagickPathExtent);
311 Search for policy tag.
313 LockSemaphoreInfo(policy_semaphore);
314 ResetLinkedListIterator(policy_cache);
315 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
316 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
318 UnlockSemaphoreInfo(policy_semaphore);
321 while (p != (PolicyInfo *) NULL)
323 if ((domain == UndefinedPolicyDomain) || (p->domain == domain))
324 if (LocaleCompare(policyname,p->name) == 0)
326 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
328 if (p != (PolicyInfo *) NULL)
329 (void) InsertValueInLinkedList(policy_cache,0,
330 RemoveElementByValueFromLinkedList(policy_cache,p));
331 UnlockSemaphoreInfo(policy_semaphore);
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 % G e t P o l i c y I n f o L i s t %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 % GetPolicyInfoList() returns any policies that match the specified pattern.
348 % The format of the GetPolicyInfoList function is:
350 % const PolicyInfo **GetPolicyInfoList(const char *pattern,
351 % size_t *number_policies,ExceptionInfo *exception)
353 % A description of each parameter follows:
355 % o pattern: Specifies a pointer to a text string containing a pattern.
357 % o number_policies: returns the number of policies in the list.
359 % o exception: return any errors or warnings in this structure.
362 MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
363 size_t *number_policies,ExceptionInfo *exception)
368 register const PolicyInfo
375 Allocate policy list.
377 assert(pattern != (char *) NULL);
378 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
379 assert(number_policies != (size_t *) NULL);
381 p=GetPolicyInfo("*",exception);
382 if (p == (const PolicyInfo *) NULL)
383 return((const PolicyInfo **) NULL);
384 policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
385 GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
386 if (policies == (const PolicyInfo **) NULL)
387 return((const PolicyInfo **) NULL);
389 Generate policy list.
391 LockSemaphoreInfo(policy_semaphore);
392 ResetLinkedListIterator(policy_cache);
393 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
394 for (i=0; p != (const PolicyInfo *) NULL; )
396 if ((p->stealth == MagickFalse) &&
397 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
399 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
401 UnlockSemaphoreInfo(policy_semaphore);
402 policies[i]=(PolicyInfo *) NULL;
403 *number_policies=(size_t) i;
408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
412 % G e t P o l i c y L i s t %
416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418 % GetPolicyList() returns any policies that match the specified pattern.
420 % The format of the GetPolicyList function is:
422 % char **GetPolicyList(const char *pattern,size_t *number_policies,
423 % ExceptionInfo *exception)
425 % A description of each parameter follows:
427 % o pattern: a pointer to a text string containing a pattern.
429 % o number_policies: returns the number of policies in the list.
431 % o exception: return any errors or warnings in this structure.
434 MagickExport char **GetPolicyList(const char *pattern,
435 size_t *number_policies,ExceptionInfo *exception)
440 register const PolicyInfo
447 Allocate policy list.
449 assert(pattern != (char *) NULL);
450 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
451 assert(number_policies != (size_t *) NULL);
453 p=GetPolicyInfo("*",exception);
454 if (p == (const PolicyInfo *) NULL)
455 return((char **) NULL);
456 policies=(char **) AcquireQuantumMemory((size_t)
457 GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
458 if (policies == (char **) NULL)
459 return((char **) NULL);
461 Generate policy list.
463 LockSemaphoreInfo(policy_semaphore);
464 ResetLinkedListIterator(policy_cache);
465 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
466 for (i=0; p != (const PolicyInfo *) NULL; )
468 if ((p->stealth == MagickFalse) &&
469 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
470 policies[i++]=ConstantString(p->name);
471 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
473 UnlockSemaphoreInfo(policy_semaphore);
474 policies[i]=(char *) NULL;
475 *number_policies=(size_t) i;
480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 % G e t P o l i c y V a l u e %
488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 % GetPolicyValue() returns the value associated with the named policy.
492 % The format of the GetPolicyValue method is:
494 % char *GetPolicyValue(const char *name)
496 % A description of each parameter follows:
498 % o policy_info: The policy info.
501 MagickExport char *GetPolicyValue(const char *name)
512 assert(name != (const char *) NULL);
513 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
514 exception=AcquireExceptionInfo();
515 policy_info=GetPolicyInfo(name,exception);
516 exception=DestroyExceptionInfo(exception);
517 if (policy_info == (PolicyInfo *) NULL)
518 return((char *) NULL);
519 value=policy_info->value;
520 if ((value == (const char *) NULL) || (*value == '\0'))
521 return((char *) NULL);
522 return(ConstantString(value));
526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530 + 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 %
534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536 % IsPolicyCacheInstantiated() determines if the policy list is instantiated.
537 % If not, it instantiates the list and returns it.
539 % The format of the IsPolicyInstantiated method is:
541 % MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
543 % A description of each parameter follows.
545 % o exception: return any errors or warnings in this structure.
548 static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
550 if (policy_cache == (LinkedListInfo *) NULL)
552 if (policy_semaphore == (SemaphoreInfo *) NULL)
553 ActivateSemaphoreInfo(&policy_semaphore);
554 LockSemaphoreInfo(policy_semaphore);
555 if (policy_cache == (LinkedListInfo *) NULL)
556 policy_cache=AcquirePolicyCache(PolicyFilename,exception);
557 UnlockSemaphoreInfo(policy_semaphore);
559 return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 % I s R i g h t s A u t h o r i z e d %
571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573 % IsRightsAuthorized() returns MagickTrue if the policy authorizes the
574 % requested rights for the specified domain.
576 % The format of the IsRightsAuthorized method is:
578 % MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
579 % const PolicyRights rights,const char *pattern)
581 % A description of each parameter follows:
583 % o domain: the policy domain.
585 % o rights: the policy rights.
587 % o pattern: the coder, delegate, filter, or path pattern.
590 MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
591 const PolicyRights rights,const char *pattern)
605 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
606 "Domain: %s; rights=%s; pattern=\"%s\" ...",
607 CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
608 CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
609 exception=AcquireExceptionInfo();
610 policy_info=GetPolicyInfo("*",exception);
611 exception=DestroyExceptionInfo(exception);
612 if (policy_info == (PolicyInfo *) NULL)
614 authorized=MagickTrue;
615 LockSemaphoreInfo(policy_semaphore);
616 ResetLinkedListIterator(policy_cache);
617 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
618 while (p != (PolicyInfo *) NULL)
620 if ((p->domain == domain) &&
621 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
623 if ((rights & ReadPolicyRights) != 0)
624 authorized=(p->rights & ReadPolicyRights) != 0 ? MagickTrue :
626 if ((rights & WritePolicyRights) != 0)
627 authorized=(p->rights & WritePolicyRights) != 0 ? MagickTrue :
629 if ((rights & ExecutePolicyRights) != 0)
630 authorized=(p->rights & ExecutePolicyRights) != 0 ? MagickTrue :
633 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
635 UnlockSemaphoreInfo(policy_semaphore);
640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 % L i s t P o l i c y I n f o %
648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650 % ListPolicyInfo() lists policies to the specified file.
652 % The format of the ListPolicyInfo method is:
654 % MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
656 % A description of each parameter follows.
658 % o file: List policy names to this file handle.
660 % o exception: return any errors or warnings in this structure.
663 MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
664 ExceptionInfo *exception)
680 List name and attributes of each policy in the list.
682 if (file == (const FILE *) NULL)
684 policy_info=GetPolicyInfoList("*",&number_policies,exception);
685 if (policy_info == (const PolicyInfo **) NULL)
687 path=(const char *) NULL;
688 for (i=0; i < (ssize_t) number_policies; i++)
690 if (policy_info[i]->stealth != MagickFalse)
692 if (((path == (const char *) NULL) ||
693 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
694 (policy_info[i]->path != (char *) NULL))
695 (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
696 path=policy_info[i]->path;
697 domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
698 policy_info[i]->domain);
699 (void) FormatLocaleFile(file," Policy: %s\n",domain);
700 if ((policy_info[i]->domain == CachePolicyDomain) ||
701 (policy_info[i]->domain == ResourcePolicyDomain) ||
702 (policy_info[i]->domain == SystemPolicyDomain))
704 if (policy_info[i]->name != (char *) NULL)
705 (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
706 if (policy_info[i]->value != (char *) NULL)
707 (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
711 (void) FormatLocaleFile(file," rights: ");
712 if (policy_info[i]->rights == NoPolicyRights)
713 (void) FormatLocaleFile(file,"None ");
714 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
715 (void) FormatLocaleFile(file,"Read ");
716 if ((policy_info[i]->rights & WritePolicyRights) != 0)
717 (void) FormatLocaleFile(file,"Write ");
718 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
719 (void) FormatLocaleFile(file,"Execute ");
720 (void) FormatLocaleFile(file,"\n");
721 if (policy_info[i]->pattern != (char *) NULL)
722 (void) FormatLocaleFile(file," pattern: %s\n",
723 policy_info[i]->pattern);
726 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 + L o a d P o l i c y C a c h e %
741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
743 % LoadPolicyCache() loads the policy configurations which provides a mapping
744 % between policy attributes and a policy domain.
746 % The format of the LoadPolicyCache method is:
748 % MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
749 % const char *filename,const size_t depth,ExceptionInfo *exception)
751 % A description of each parameter follows:
753 % o xml: The policy list in XML format.
755 % o filename: The policy list filename.
757 % o depth: depth of <include /> statements.
759 % o exception: return any errors or warnings in this structure.
762 static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
763 const char *filename,const size_t depth,ExceptionInfo *exception)
766 keyword[MagickPathExtent],
782 Load the policy map file.
784 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
785 "Loading policy file \"%s\" ...",filename);
786 if (xml == (char *) NULL)
789 policy_info=(PolicyInfo *) NULL;
790 token=AcquireString(xml);
791 extent=strlen(token)+MagickPathExtent;
792 for (q=(const char *) xml; *q != '\0'; )
797 GetNextToken(q,&q,extent,token);
800 (void) CopyMagickString(keyword,token,MagickPathExtent);
801 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
806 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
807 GetNextToken(q,&q,extent,token);
810 if (LocaleNCompare(keyword,"<!--",4) == 0)
815 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
816 GetNextToken(q,&q,extent,token);
819 if (LocaleCompare(keyword,"<include") == 0)
824 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
826 (void) CopyMagickString(keyword,token,MagickPathExtent);
827 GetNextToken(q,&q,extent,token);
830 GetNextToken(q,&q,extent,token);
831 if (LocaleCompare(keyword,"file") == 0)
834 (void) ThrowMagickException(exception,GetMagickModule(),
835 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
839 path[MagickPathExtent],
842 GetPathComponent(filename,HeadPath,path);
844 (void) ConcatenateMagickString(path,DirectorySeparator,
846 if (*token == *DirectorySeparator)
847 (void) CopyMagickString(path,token,MagickPathExtent);
849 (void) ConcatenateMagickString(path,token,MagickPathExtent);
850 file_xml=FileToXML(path,~0UL);
851 if (file_xml != (char *) NULL)
853 status&=LoadPolicyCache(cache,file_xml,path,
855 file_xml=DestroyString(file_xml);
862 if (LocaleCompare(keyword,"<policy") == 0)
867 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
868 if (policy_info == (PolicyInfo *) NULL)
869 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
870 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
871 policy_info->path=ConstantString(filename);
872 policy_info->exempt=MagickFalse;
873 policy_info->signature=MagickCoreSignature;
876 if (policy_info == (PolicyInfo *) NULL)
878 if ((LocaleCompare(keyword,"/>") == 0) ||
879 (LocaleCompare(keyword,"</policy>") == 0))
881 status=AppendValueToLinkedList(cache,policy_info);
882 if (status == MagickFalse)
883 (void) ThrowMagickException(exception,GetMagickModule(),
884 ResourceLimitError,"MemoryAllocationFailed","`%s'",
886 policy_info=(PolicyInfo *) NULL;
889 GetNextToken(q,(const char **) NULL,extent,token);
892 GetNextToken(q,&q,extent,token);
893 GetNextToken(q,&q,extent,token);
899 if (LocaleCompare((char *) keyword,"domain") == 0)
901 policy_info->domain=(PolicyDomain) ParseCommandOption(
902 MagickPolicyDomainOptions,MagickTrue,token);
910 if (LocaleCompare((char *) keyword,"name") == 0)
912 policy_info->name=ConstantString(token);
920 if (LocaleCompare((char *) keyword,"pattern") == 0)
922 policy_info->pattern=ConstantString(token);
930 if (LocaleCompare((char *) keyword,"rights") == 0)
932 policy_info->rights=(PolicyRights) ParseCommandOption(
933 MagickPolicyRightsOptions,MagickTrue,token);
941 if (LocaleCompare((char *) keyword,"stealth") == 0)
943 policy_info->stealth=IsStringTrue(token);
951 if (LocaleCompare((char *) keyword,"value") == 0)
953 policy_info->value=ConstantString(token);
962 token=(char *) RelinquishMagickMemory(token);
963 return(status != 0 ? MagickTrue : MagickFalse);
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 + P o l i c y C o m p o n e n t G e n e s i s %
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977 % PolicyComponentGenesis() instantiates the policy component.
979 % The format of the PolicyComponentGenesis method is:
981 % MagickBooleanType PolicyComponentGenesis(void)
984 MagickPrivate MagickBooleanType PolicyComponentGenesis(void)
986 if (policy_semaphore == (SemaphoreInfo *) NULL)
987 policy_semaphore=AcquireSemaphoreInfo();
992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996 + P o l i c y C o m p o n e n t T e r m i n u s %
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002 % PolicyComponentTerminus() destroys the policy component.
1004 % The format of the PolicyComponentTerminus method is:
1006 % PolicyComponentTerminus(void)
1010 static void *DestroyPolicyElement(void *policy_info)
1015 p=(PolicyInfo *) policy_info;
1016 if (p->exempt == MagickFalse)
1018 if (p->value != (char *) NULL)
1019 p->value=DestroyString(p->value);
1020 if (p->pattern != (char *) NULL)
1021 p->pattern=DestroyString(p->pattern);
1022 if (p->name != (char *) NULL)
1023 p->name=DestroyString(p->name);
1024 if (p->path != (char *) NULL)
1025 p->path=DestroyString(p->path);
1027 p=(PolicyInfo *) RelinquishMagickMemory(p);
1028 return((void *) NULL);
1031 MagickPrivate void PolicyComponentTerminus(void)
1033 if (policy_semaphore == (SemaphoreInfo *) NULL)
1034 ActivateSemaphoreInfo(&policy_semaphore);
1035 LockSemaphoreInfo(policy_semaphore);
1036 if (policy_cache != (LinkedListInfo *) NULL)
1037 policy_cache=DestroyLinkedList(policy_cache,DestroyPolicyElement);
1038 UnlockSemaphoreInfo(policy_semaphore);
1039 RelinquishSemaphoreInfo(&policy_semaphore);
1043 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1047 % S e t M a g i c k S e c u r i t y P o l i c y %
1051 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1053 % SetMagickSecurityPolicy() sets the ImageMagick security policy. It returns
1054 % MagickFalse if the policy is already set or if the policy does not parse.
1056 % The format of the SetMagickSecurityPolicy method is:
1058 % MagickBooleanType SetMagickSecurityPolicy(const char *policy,
1059 % ExceptionInfo *exception)
1061 % A description of each parameter follows:
1063 % o policy: the security policy in the XML format.
1065 % o exception: return any errors or warnings in this structure.
1068 MagickExport MagickBooleanType SetMagickSecurityPolicy(const char *policy,
1069 ExceptionInfo *exception)
1077 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
1078 return((PolicyInfo *) NULL);
1079 LockSemaphoreInfo(policy_semaphore);
1080 ResetLinkedListIterator(policy_cache);
1081 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
1082 if ((p != (PolicyInfo *) NULL) && (p->domain != UndefinedPolicyDomain))
1084 UnlockSemaphoreInfo(policy_semaphore);
1085 return(MagickFalse);
1087 UnlockSemaphoreInfo(policy_semaphore);
1088 status=LoadPolicyCache(policy_cache,policy,"[user-policy]",0,exception);
1089 if (status == MagickFalse)
1090 return(MagickFalse);
1091 return(ResourceComponentGenesis());