43 #include "magick/studio.h"
44 #include "magick/client.h"
45 #include "magick/configure.h"
46 #include "magick/exception.h"
47 #include "magick/exception-private.h"
48 #include "magick/locale_.h"
49 #include "magick/memory_.h"
50 #include "magick/monitor.h"
51 #include "magick/monitor-private.h"
52 #include "magick/option.h"
53 #include "magick/policy.h"
54 #include "magick/policy-private.h"
55 #include "magick/resource_.h"
56 #include "magick/semaphore.h"
57 #include "magick/string_.h"
58 #include "magick/token.h"
59 #include "magick/utility.h"
60 #include "magick/xml-tree.h"
61 #include "magick/xml-tree-private.h"
66 #define PolicyFilename "policy.xml"
119 { UndefinedPolicyDomain, UndefinedPolicyRights, (
const char *) NULL,
120 (
const char *) NULL, (
const char *) NULL }
132 static MagickBooleanType
134 LoadPolicyCache(
LinkedListInfo *,
const char *,
const char *,
const size_t,
178 cache=NewLinkedList(0);
180 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
182 #if MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
183 status=LoadPolicyCache(cache,ZeroConfigurationPolicy,
"[zero-configuration]",0,
193 options=GetConfigureOptions(filename,exception);
194 option=(
const StringInfo *) GetNextValueInLinkedList(options);
197 status&=LoadPolicyCache(cache,(
const char *) GetStringInfoDatum(option),
198 GetStringInfoPath(option),0,exception);
199 option=(
const StringInfo *) GetNextValueInLinkedList(options);
201 options=DestroyConfigureOptions(options);
207 for (i=0; i < (ssize_t) (
sizeof(PolicyMap)/
sizeof(*PolicyMap)); i++)
216 policy_info=(
PolicyInfo *) AcquireMagickMemory(
sizeof(*policy_info));
219 (void) ThrowMagickException(exception,GetMagickModule(),
220 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
221 p->name == (
char *) NULL ?
"" : p->name);
224 (void) memset(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);
269 policyname[MagickPathExtent];
281 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
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);
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);
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);
323 if ((domain == UndefinedPolicyDomain) || (p->domain == domain))
324 if (LocaleCompare(policyname,p->name) == 0)
326 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
329 (
void) InsertValueInLinkedList(policy_cache,0,
330 RemoveElementByValueFromLinkedList(policy_cache,p));
331 UnlockSemaphoreInfo(policy_semaphore);
362 MagickExport
const PolicyInfo **GetPolicyInfoList(
const char *pattern,
377 assert(pattern != (
char *) NULL);
378 assert(number_policies != (
size_t *) NULL);
379 if (IsEventLogging() != MagickFalse)
380 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
382 p=GetPolicyInfo(
"*",exception);
385 policies=(
const PolicyInfo **) AcquireQuantumMemory((
size_t)
386 GetNumberOfElementsInLinkedList(policy_cache)+1UL,
sizeof(*policies));
392 LockSemaphoreInfo(policy_semaphore);
393 ResetLinkedListIterator(policy_cache);
394 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
397 if ((p->stealth == MagickFalse) &&
398 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
400 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
402 UnlockSemaphoreInfo(policy_semaphore);
404 *number_policies=(size_t) i;
436 static char *AcquirePolicyString(
const char *source,
const size_t pad)
445 if (source != (
char *) NULL)
446 length+=strlen(source);
447 destination=(
char *) NULL;
449 destination=(
char *) AcquireMagickMemory((length+pad)*
sizeof(*destination));
450 if (destination == (
char *) NULL)
451 ThrowFatalException(ResourceLimitFatalError,
"UnableToAcquireString");
452 if (source != (
char *) NULL)
453 (
void) memcpy(destination,source,length*
sizeof(*destination));
454 destination[length]=
'\0';
458 MagickExport
char **GetPolicyList(
const char *pattern,
size_t *number_policies,
473 assert(pattern != (
char *) NULL);
474 assert(number_policies != (
size_t *) NULL);
475 if (IsEventLogging() != MagickFalse)
476 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
478 p=GetPolicyInfo(
"*",exception);
480 return((
char **) NULL);
481 policies=(
char **) AcquireQuantumMemory((
size_t)
482 GetNumberOfElementsInLinkedList(policy_cache)+1UL,
sizeof(*policies));
483 if (policies == (
char **) NULL)
484 return((
char **) NULL);
488 LockSemaphoreInfo(policy_semaphore);
489 ResetLinkedListIterator(policy_cache);
490 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
493 if ((p->stealth == MagickFalse) &&
494 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
495 policies[i++]=AcquirePolicyString(p->name,1);
496 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
498 UnlockSemaphoreInfo(policy_semaphore);
499 policies[i]=(
char *) NULL;
500 *number_policies=(size_t) i;
526 MagickExport
char *GetPolicyValue(
const char *name)
537 assert(name != (
const char *) NULL);
538 if (IsEventLogging() != MagickFalse)
539 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",name);
540 exception=AcquireExceptionInfo();
541 policy_info=GetPolicyInfo(name,exception);
542 exception=DestroyExceptionInfo(exception);
544 return((
char *) NULL);
545 value=policy_info->value;
546 if ((value == (
const char *) NULL) || (*value ==
'\0'))
547 return((
char *) NULL);
548 return(AcquirePolicyString(value,1));
574 static MagickBooleanType IsPolicyCacheInstantiated(
ExceptionInfo *exception)
578 GetMaxMemoryRequest();
580 ActivateSemaphoreInfo(&policy_semaphore);
581 LockSemaphoreInfo(policy_semaphore);
583 policy_cache=AcquirePolicyCache(PolicyFilename,exception);
584 UnlockSemaphoreInfo(policy_semaphore);
586 return(policy_cache != (
LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
617 MagickExport MagickBooleanType IsRightsAuthorized(
const PolicyDomain domain,
618 const PolicyRights rights,
const char *pattern)
632 if ((GetLogEventMask() & PolicyEvent) != 0)
633 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
634 "Domain: %s; rights=%s; pattern=\"%s\" ...",
635 CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
636 CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
637 exception=AcquireExceptionInfo();
638 policy_info=GetPolicyInfo(
"*",exception);
639 exception=DestroyExceptionInfo(exception);
642 authorized=MagickTrue;
643 LockSemaphoreInfo(policy_semaphore);
644 ResetLinkedListIterator(policy_cache);
645 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
648 if ((p->domain == domain) &&
649 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
651 if ((rights & ReadPolicyRights) != 0)
652 authorized=(p->rights & ReadPolicyRights) != 0 ? MagickTrue :
654 if ((rights & WritePolicyRights) != 0)
655 authorized=(p->rights & WritePolicyRights) != 0 ? MagickTrue :
657 if ((rights & ExecutePolicyRights) != 0)
658 authorized=(p->rights & ExecutePolicyRights) != 0 ? MagickTrue :
661 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
663 UnlockSemaphoreInfo(policy_semaphore);
691 MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
710 if (file == (
const FILE *) NULL)
712 policy_info=GetPolicyInfoList(
"*",&number_policies,exception);
713 if (policy_info == (
const PolicyInfo **) NULL)
715 path=(
const char *) NULL;
716 for (i=0; i < (ssize_t) number_policies; i++)
718 if (policy_info[i]->stealth != MagickFalse)
720 if (((path == (
const char *) NULL) ||
721 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
722 (policy_info[i]->path != (
char *) NULL))
723 (
void) FormatLocaleFile(file,
"\nPath: %s\n",policy_info[i]->path);
724 path=policy_info[i]->path;
725 domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
726 policy_info[i]->domain);
727 (void) FormatLocaleFile(file,
" Policy: %s\n",domain);
728 if ((policy_info[i]->domain == CachePolicyDomain) ||
729 (policy_info[i]->domain == ResourcePolicyDomain) ||
730 (policy_info[i]->domain == SystemPolicyDomain))
732 if (policy_info[i]->name != (
char *) NULL)
733 (
void) FormatLocaleFile(file,
" name: %s\n",policy_info[i]->name);
734 if (policy_info[i]->value != (
char *) NULL)
735 (void) FormatLocaleFile(file,
" value: %s\n",policy_info[i]->value);
739 (void) FormatLocaleFile(file,
" rights: ");
740 if (policy_info[i]->rights == NoPolicyRights)
741 (void) FormatLocaleFile(file,
"None ");
742 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
743 (
void) FormatLocaleFile(file,
"Read ");
744 if ((policy_info[i]->rights & WritePolicyRights) != 0)
745 (void) FormatLocaleFile(file,
"Write ");
746 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
747 (
void) FormatLocaleFile(file,
"Execute ");
748 (void) FormatLocaleFile(file,
"\n");
749 if (policy_info[i]->pattern != (
char *) NULL)
750 (
void) FormatLocaleFile(file,
" pattern: %s\n",
751 policy_info[i]->pattern);
754 policy_info=(
const PolicyInfo **) RelinquishMagickMemory((
void *)
790 static MagickBooleanType LoadPolicyCache(
LinkedListInfo *cache,
const char *xml,
791 const char *filename,
const size_t depth,
ExceptionInfo *exception)
794 keyword[MagickPathExtent],
812 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
813 "Loading policy file \"%s\" ...",filename);
814 if (xml == (
char *) NULL)
818 token=AcquirePolicyString(xml,MagickPathExtent);
819 extent=strlen(token)+MagickPathExtent;
820 for (q=(
const char *) xml; *q !=
'\0'; )
825 (void) GetNextToken(q,&q,extent,token);
828 (void) CopyMagickString(keyword,token,MagickPathExtent);
829 if (LocaleNCompare(keyword,
"<!DOCTYPE",9) == 0)
834 while ((LocaleNCompare(q,
"]>",2) != 0) && (*q !=
'\0'))
835 (
void) GetNextToken(q,&q,extent,token);
838 if (LocaleNCompare(keyword,
"<!--",4) == 0)
843 while ((LocaleNCompare(q,
"->",2) != 0) && (*q !=
'\0'))
844 (void) GetNextToken(q,&q,extent,token);
847 if (LocaleCompare(keyword,
"<include") == 0)
852 while (((*token !=
'/') && (*(token+1) !=
'>')) && (*q !=
'\0'))
854 (void) CopyMagickString(keyword,token,MagickPathExtent);
855 (void) GetNextToken(q,&q,extent,token);
858 (void) GetNextToken(q,&q,extent,token);
859 if (LocaleCompare(keyword,
"file") == 0)
861 if (depth > MagickMaxRecursionDepth)
862 (void) ThrowMagickException(exception,GetMagickModule(),
863 ConfigureError,
"IncludeElementNestedTooDeeply",
"`%s'",token);
867 path[MagickPathExtent],
870 GetPathComponent(filename,HeadPath,path);
872 (void) ConcatenateMagickString(path,DirectorySeparator,
874 if (*token == *DirectorySeparator)
875 (void) CopyMagickString(path,token,MagickPathExtent);
877 (
void) ConcatenateMagickString(path,token,MagickPathExtent);
878 xml=FileToXML(path,~0UL);
879 if (xml != (
char *) NULL)
881 status&=LoadPolicyCache(cache,xml,path,depth+1,
883 xml=(
char *) RelinquishMagickMemory(xml);
890 if (LocaleCompare(keyword,
"<policy") == 0)
895 policy_info=(
PolicyInfo *) AcquireMagickMemory(
sizeof(*policy_info));
897 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
898 (void) memset(policy_info,0,
sizeof(*policy_info));
899 policy_info->path=AcquirePolicyString(filename,1);
900 policy_info->exempt=MagickFalse;
901 policy_info->signature=MagickCoreSignature;
906 if ((LocaleCompare(keyword,
"/>") == 0) ||
907 (LocaleCompare(keyword,
"</policy>") == 0))
909 status=AppendValueToLinkedList(cache,policy_info);
910 if (status == MagickFalse)
911 (void) ThrowMagickException(exception,GetMagickModule(),
912 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
917 (void) GetNextToken(q,(
const char **) NULL,extent,token);
920 (void) GetNextToken(q,&q,extent,token);
921 (void) GetNextToken(q,&q,extent,token);
927 if (LocaleCompare((
char *) keyword,
"domain") == 0)
929 policy_info->domain=(PolicyDomain) ParseCommandOption(
930 MagickPolicyDomainOptions,MagickTrue,token);
938 if (LocaleCompare((
char *) keyword,
"name") == 0)
940 policy_info->name=AcquirePolicyString(token,1);
948 if (LocaleCompare((
char *) keyword,
"pattern") == 0)
950 policy_info->pattern=AcquirePolicyString(token,1);
958 if (LocaleCompare((
char *) keyword,
"rights") == 0)
960 policy_info->rights=(PolicyRights) ParseCommandOption(
961 MagickPolicyRightsOptions,MagickTrue,token);
969 if (LocaleCompare((
char *) keyword,
"stealth") == 0)
971 policy_info->stealth=IsMagickTrue(token);
979 if (LocaleCompare((
char *) keyword,
"value") == 0)
981 policy_info->value=AcquirePolicyString(token,1);
990 token=(
char *) RelinquishMagickMemory(token);
991 return(status != 0 ? MagickTrue : MagickFalse);
1012 MagickExport MagickBooleanType PolicyComponentGenesis(
void)
1015 policy_semaphore=AllocateSemaphoreInfo();
1038 static void *DestroyPolicyElement(
void *policy_info)
1044 if (p->exempt == MagickFalse)
1046 if (p->value != (
char *) NULL)
1047 p->value=DestroyString(p->value);
1048 if (p->pattern != (
char *) NULL)
1049 p->pattern=DestroyString(p->pattern);
1050 if (p->name != (
char *) NULL)
1051 p->name=DestroyString(p->name);
1052 if (p->path != (
char *) NULL)
1053 p->path=DestroyString(p->path);
1056 return((
void *) NULL);
1059 MagickExport
void PolicyComponentTerminus(
void)
1062 ActivateSemaphoreInfo(&policy_semaphore);
1063 LockSemaphoreInfo(policy_semaphore);
1065 policy_cache=DestroyLinkedList(policy_cache,DestroyPolicyElement);
1066 UnlockSemaphoreInfo(policy_semaphore);
1067 DestroySemaphoreInfo(&policy_semaphore);
1096 MagickExport MagickBooleanType SetMagickSecurityPolicy(
const char *policy,
1106 if (policy == (
const char *) NULL)
1107 return(MagickFalse);
1108 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
1109 return(MagickFalse);
1110 LockSemaphoreInfo(policy_semaphore);
1111 ResetLinkedListIterator(policy_cache);
1112 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
1113 if ((p != (
PolicyInfo *) NULL) && (p->domain != UndefinedPolicyDomain))
1115 UnlockSemaphoreInfo(policy_semaphore);
1116 return(MagickFalse);
1118 UnlockSemaphoreInfo(policy_semaphore);
1119 status=LoadPolicyCache(policy_cache,policy,
"[user-policy]",0,exception);
1120 if (status == MagickFalse)
1121 return(MagickFalse);
1122 return(ResourceComponentGenesis());