43 #include "MagickCore/studio.h"
44 #include "MagickCore/cache-private.h"
45 #include "MagickCore/client.h"
46 #include "MagickCore/configure.h"
47 #include "MagickCore/configure-private.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/magick-private.h"
51 #include "MagickCore/memory_.h"
52 #include "MagickCore/memory-private.h"
53 #include "MagickCore/monitor.h"
54 #include "MagickCore/monitor-private.h"
55 #include "MagickCore/option.h"
56 #include "MagickCore/policy.h"
57 #include "MagickCore/policy-private.h"
58 #include "MagickCore/resource_.h"
59 #include "MagickCore/resource-private.h"
60 #include "MagickCore/semaphore.h"
61 #include "MagickCore/stream-private.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/string-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
67 #include "MagickCore/xml-tree.h"
68 #include "MagickCore/xml-tree-private.h"
73 #define PolicyFilename "policy.xml"
126 { UndefinedPolicyDomain, UndefinedPolicyRights, (
const char *) NULL,
127 (
const char *) NULL, (
const char *) NULL }
139 static MagickBooleanType
141 LoadPolicyCache(
LinkedListInfo *,
const char *,
const char *,
const size_t,
185 cache=NewLinkedList(0);
187 #if MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
189 status=LoadPolicyCache(cache,ZeroConfigurationPolicy,
"[zero-configuration]",0,
199 options=GetConfigureOptions(filename,exception);
200 option=(
const StringInfo *) GetNextValueInLinkedList(options);
203 status&=LoadPolicyCache(cache,(
const char *) GetStringInfoDatum(option),
204 GetStringInfoPath(option),0,exception);
205 option=(
const StringInfo *) GetNextValueInLinkedList(options);
207 options=DestroyConfigureOptions(options);
213 for (i=0; i < (ssize_t) (
sizeof(PolicyMap)/
sizeof(*PolicyMap)); i++)
222 policy_info=(
PolicyInfo *) AcquireMagickMemory(
sizeof(*policy_info));
225 (void) ThrowMagickException(exception,GetMagickModule(),
226 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
227 p->name == (
char *) NULL ?
"" : p->name);
230 (void) memset(policy_info,0,
sizeof(*policy_info));
231 policy_info->path=(
char *)
"[built-in]";
232 policy_info->domain=p->domain;
233 policy_info->rights=p->rights;
234 policy_info->name=(
char *) p->name;
235 policy_info->pattern=(
char *) p->pattern;
236 policy_info->value=(
char *) p->value;
237 policy_info->exempt=MagickTrue;
238 policy_info->signature=MagickCoreSignature;
239 status&=AppendValueToLinkedList(cache,policy_info);
240 if (status == MagickFalse)
241 (void) ThrowMagickException(exception,GetMagickModule(),
242 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",policy_info->name);
275 policyname[MagickPathExtent];
287 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
293 if (name != (
const char *) NULL)
294 (void) CopyMagickString(policyname,name,MagickPathExtent);
295 for (q=policyname; *q !=
'\0'; q++)
297 if (isspace((
int) ((
unsigned char) *q)) == 0)
299 (void) CopyMagickString(q,q+1,MagickPathExtent);
305 domain=UndefinedPolicyDomain;
306 for (q=policyname; *q !=
'\0'; q++)
311 domain=(PolicyDomain) ParseCommandOption(MagickPolicyDomainOptions,
312 MagickTrue,policyname);
313 (void) CopyMagickString(policyname,q+1,MagickPathExtent);
319 LockSemaphoreInfo(policy_semaphore);
320 ResetLinkedListIterator(policy_cache);
321 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
322 if ((name == (
const char *) NULL) || (LocaleCompare(name,
"*") == 0))
324 UnlockSemaphoreInfo(policy_semaphore);
329 if ((domain == UndefinedPolicyDomain) || (p->domain == domain))
330 if (LocaleCompare(policyname,p->name) == 0)
332 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
335 (
void) InsertValueInLinkedList(policy_cache,0,
336 RemoveElementByValueFromLinkedList(policy_cache,p));
337 UnlockSemaphoreInfo(policy_semaphore);
368 MagickExport
const PolicyInfo **GetPolicyInfoList(
const char *pattern,
383 assert(pattern != (
char *) NULL);
384 assert(number_policies != (
size_t *) NULL);
385 if (IsEventLogging() != MagickFalse)
386 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
388 p=GetPolicyInfo(
"*",exception);
391 policies=(
const PolicyInfo **) AcquireQuantumMemory((
size_t)
392 GetNumberOfElementsInLinkedList(policy_cache)+1UL,
sizeof(*policies));
398 LockSemaphoreInfo(policy_semaphore);
399 ResetLinkedListIterator(policy_cache);
400 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
403 if ((p->stealth == MagickFalse) &&
404 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
406 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
408 UnlockSemaphoreInfo(policy_semaphore);
410 *number_policies=(size_t) i;
442 static char *AcquirePolicyString(
const char *source,
const size_t pad)
451 if (source != (
char *) NULL)
452 length+=strlen(source);
453 destination=(
char *) NULL;
456 destination=(
char *) AcquireMagickMemory((length+pad)*
sizeof(*destination));
457 if (destination == (
char *) NULL)
458 ThrowFatalException(ResourceLimitFatalError,
"UnableToAcquireString");
459 if (source != (
char *) NULL)
460 (
void) memcpy(destination,source,length*
sizeof(*destination));
461 destination[length]=
'\0';
465 MagickExport
char **GetPolicyList(
const char *pattern,
size_t *number_policies,
480 assert(pattern != (
char *) NULL);
481 assert(number_policies != (
size_t *) NULL);
482 if (IsEventLogging() != MagickFalse)
483 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
485 p=GetPolicyInfo(
"*",exception);
487 return((
char **) NULL);
488 policies=(
char **) AcquireQuantumMemory((
size_t)
489 GetNumberOfElementsInLinkedList(policy_cache)+1UL,
sizeof(*policies));
490 if (policies == (
char **) NULL)
491 return((
char **) NULL);
495 LockSemaphoreInfo(policy_semaphore);
496 ResetLinkedListIterator(policy_cache);
497 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
500 if ((p->stealth == MagickFalse) &&
501 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
502 policies[i++]=AcquirePolicyString(p->name,1);
503 p=(
const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
505 UnlockSemaphoreInfo(policy_semaphore);
506 policies[i]=(
char *) NULL;
507 *number_policies=(size_t) i;
533 MagickExport
char *GetPolicyValue(
const char *name)
544 assert(name != (
const char *) NULL);
545 if (IsEventLogging() != MagickFalse)
546 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",name);
547 exception=AcquireExceptionInfo();
548 policy_info=GetPolicyInfo(name,exception);
549 exception=DestroyExceptionInfo(exception);
551 return((
char *) NULL);
552 value=policy_info->value;
553 if ((value == (
const char *) NULL) || (*value ==
'\0'))
554 return((
char *) NULL);
555 return(AcquirePolicyString(value,1));
581 static MagickBooleanType IsPolicyCacheInstantiated(
ExceptionInfo *exception)
585 GetMaxMemoryRequest();
587 ActivateSemaphoreInfo(&policy_semaphore);
588 LockSemaphoreInfo(policy_semaphore);
590 policy_cache=AcquirePolicyCache(PolicyFilename,exception);
591 UnlockSemaphoreInfo(policy_semaphore);
593 return(policy_cache != (
LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
624 MagickExport MagickBooleanType IsRightsAuthorized(
const PolicyDomain domain,
625 const PolicyRights rights,
const char *pattern)
639 if ((GetLogEventMask() & PolicyEvent) != 0)
640 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
641 "Domain: %s; rights=%s; pattern=\"%s\" ...",
642 CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
643 CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
644 exception=AcquireExceptionInfo();
645 policy_info=GetPolicyInfo(
"*",exception);
646 exception=DestroyExceptionInfo(exception);
649 authorized=MagickTrue;
650 LockSemaphoreInfo(policy_semaphore);
651 ResetLinkedListIterator(policy_cache);
652 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
655 if ((p->domain == domain) &&
656 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
658 if ((rights & ReadPolicyRights) != 0)
659 authorized=(p->rights & ReadPolicyRights) != 0 ? MagickTrue :
661 if ((rights & WritePolicyRights) != 0)
662 authorized=(p->rights & WritePolicyRights) != 0 ? MagickTrue :
664 if ((rights & ExecutePolicyRights) != 0)
665 authorized=(p->rights & ExecutePolicyRights) != 0 ? MagickTrue :
668 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
670 UnlockSemaphoreInfo(policy_semaphore);
698 MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
717 if (file == (
const FILE *) NULL)
719 policy_info=GetPolicyInfoList(
"*",&number_policies,exception);
720 if (policy_info == (
const PolicyInfo **) NULL)
722 path=(
const char *) NULL;
723 for (i=0; i < (ssize_t) number_policies; i++)
725 if (policy_info[i]->stealth != MagickFalse)
727 if (((path == (
const char *) NULL) ||
728 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
729 (policy_info[i]->path != (
char *) NULL))
730 (
void) FormatLocaleFile(file,
"\nPath: %s\n",policy_info[i]->path);
731 path=policy_info[i]->path;
732 domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
733 policy_info[i]->domain);
734 (void) FormatLocaleFile(file,
" Policy: %s\n",domain);
735 if ((policy_info[i]->domain == CachePolicyDomain) ||
736 (policy_info[i]->domain == ResourcePolicyDomain) ||
737 (policy_info[i]->domain == SystemPolicyDomain))
739 if (policy_info[i]->name != (
char *) NULL)
740 (
void) FormatLocaleFile(file,
" name: %s\n",policy_info[i]->name);
741 if (policy_info[i]->value != (
char *) NULL)
742 (void) FormatLocaleFile(file,
" value: %s\n",policy_info[i]->value);
746 (void) FormatLocaleFile(file,
" rights: ");
747 if (policy_info[i]->rights == NoPolicyRights)
748 (void) FormatLocaleFile(file,
"None ");
749 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
750 (
void) FormatLocaleFile(file,
"Read ");
751 if ((policy_info[i]->rights & WritePolicyRights) != 0)
752 (void) FormatLocaleFile(file,
"Write ");
753 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
754 (
void) FormatLocaleFile(file,
"Execute ");
755 (void) FormatLocaleFile(file,
"\n");
756 if (policy_info[i]->pattern != (
char *) NULL)
757 (
void) FormatLocaleFile(file,
" pattern: %s\n",
758 policy_info[i]->pattern);
761 policy_info=(
const PolicyInfo **) RelinquishMagickMemory((
void *)
797 static MagickBooleanType LoadPolicyCache(
LinkedListInfo *cache,
const char *xml,
798 const char *filename,
const size_t depth,
ExceptionInfo *exception)
801 keyword[MagickPathExtent],
819 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
820 "Loading policy file \"%s\" ...",filename);
821 if (xml == (
char *) NULL)
825 token=AcquirePolicyString(xml,MagickPathExtent);
826 extent=strlen(token)+MagickPathExtent;
827 for (q=(
const char *) xml; *q !=
'\0'; )
832 (void) GetNextToken(q,&q,extent,token);
835 (void) CopyMagickString(keyword,token,MagickPathExtent);
836 if (LocaleNCompare(keyword,
"<!DOCTYPE",9) == 0)
841 while ((LocaleNCompare(q,
"]>",2) != 0) && (*q !=
'\0'))
842 (
void) GetNextToken(q,&q,extent,token);
845 if (LocaleNCompare(keyword,
"<!--",4) == 0)
850 while ((LocaleNCompare(q,
"->",2) != 0) && (*q !=
'\0'))
851 (void) GetNextToken(q,&q,extent,token);
854 if (LocaleCompare(keyword,
"<include") == 0)
859 while (((*token !=
'/') && (*(token+1) !=
'>')) && (*q !=
'\0'))
861 (void) CopyMagickString(keyword,token,MagickPathExtent);
862 (void) GetNextToken(q,&q,extent,token);
865 (void) GetNextToken(q,&q,extent,token);
866 if (LocaleCompare(keyword,
"file") == 0)
868 if (depth > MagickMaxRecursionDepth)
869 (void) ThrowMagickException(exception,GetMagickModule(),
870 ConfigureError,
"IncludeElementNestedTooDeeply",
"`%s'",token);
874 path[MagickPathExtent],
877 GetPathComponent(filename,HeadPath,path);
879 (void) ConcatenateMagickString(path,DirectorySeparator,
881 if (*token == *DirectorySeparator)
882 (void) CopyMagickString(path,token,MagickPathExtent);
884 (
void) ConcatenateMagickString(path,token,MagickPathExtent);
885 file_xml=FileToXML(path,~0UL);
886 if (file_xml != (
char *) NULL)
888 status&=LoadPolicyCache(cache,file_xml,path,depth+1,
890 file_xml=DestroyString(file_xml);
897 if (LocaleCompare(keyword,
"<policy") == 0)
902 policy_info=(
PolicyInfo *) AcquireCriticalMemory(
sizeof(*policy_info));
903 (void) memset(policy_info,0,
sizeof(*policy_info));
904 policy_info->path=AcquirePolicyString(filename,1);
905 policy_info->exempt=MagickFalse;
906 policy_info->signature=MagickCoreSignature;
911 if ((LocaleCompare(keyword,
"/>") == 0) ||
912 (LocaleCompare(keyword,
"</policy>") == 0))
914 status=AppendValueToLinkedList(cache,policy_info);
915 if (status == MagickFalse)
916 (void) ThrowMagickException(exception,GetMagickModule(),
917 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
922 (void) GetNextToken(q,(
const char **) NULL,extent,token);
925 (void) GetNextToken(q,&q,extent,token);
926 (void) GetNextToken(q,&q,extent,token);
932 if (LocaleCompare((
char *) keyword,
"domain") == 0)
934 policy_info->domain=(PolicyDomain) ParseCommandOption(
935 MagickPolicyDomainOptions,MagickTrue,token);
943 if (LocaleCompare((
char *) keyword,
"name") == 0)
945 policy_info->name=AcquirePolicyString(token,1);
953 if (LocaleCompare((
char *) keyword,
"pattern") == 0)
955 policy_info->pattern=AcquirePolicyString(token,1);
963 if (LocaleCompare((
char *) keyword,
"rights") == 0)
965 policy_info->rights=(PolicyRights) ParseCommandOption(
966 MagickPolicyRightsOptions,MagickTrue,token);
974 if (LocaleCompare((
char *) keyword,
"stealth") == 0)
976 policy_info->stealth=IsStringTrue(token);
984 if (LocaleCompare((
char *) keyword,
"value") == 0)
986 policy_info->value=AcquirePolicyString(token,1);
995 token=(
char *) RelinquishMagickMemory(token);
996 return(status != 0 ? MagickTrue : MagickFalse);
1017 MagickPrivate MagickBooleanType PolicyComponentGenesis(
void)
1020 policy_semaphore=AcquireSemaphoreInfo();
1043 static void *DestroyPolicyElement(
void *policy_info)
1049 if (p->exempt == MagickFalse)
1051 if (p->value != (
char *) NULL)
1052 p->value=DestroyString(p->value);
1053 if (p->pattern != (
char *) NULL)
1054 p->pattern=DestroyString(p->pattern);
1055 if (p->name != (
char *) NULL)
1056 p->name=DestroyString(p->name);
1057 if (p->path != (
char *) NULL)
1058 p->path=DestroyString(p->path);
1061 return((
void *) NULL);
1064 MagickPrivate
void PolicyComponentTerminus(
void)
1067 ActivateSemaphoreInfo(&policy_semaphore);
1068 LockSemaphoreInfo(policy_semaphore);
1070 policy_cache=DestroyLinkedList(policy_cache,DestroyPolicyElement);
1071 UnlockSemaphoreInfo(policy_semaphore);
1072 RelinquishSemaphoreInfo(&policy_semaphore);
1101 MagickExport MagickBooleanType SetMagickSecurityPolicy(
const char *policy,
1111 if (policy == (
const char *) NULL)
1112 return(MagickFalse);
1113 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
1114 return(MagickFalse);
1115 LockSemaphoreInfo(policy_semaphore);
1116 ResetLinkedListIterator(policy_cache);
1117 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
1118 if ((p != (
PolicyInfo *) NULL) && (p->domain != UndefinedPolicyDomain))
1120 UnlockSemaphoreInfo(policy_semaphore);
1121 return(MagickFalse);
1123 UnlockSemaphoreInfo(policy_semaphore);
1124 status=LoadPolicyCache(policy_cache,policy,
"[user-policy]",0,exception);
1125 if (status == MagickFalse)
1126 return(MagickFalse);
1127 return(ResourceComponentGenesis());
1164 static MagickBooleanType SetPolicyValue(
const PolicyDomain domain,
1165 const char *name,
const char *value)
1174 LockSemaphoreInfo(policy_semaphore);
1175 ResetLinkedListIterator(policy_cache);
1176 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
1179 if ((p->domain == domain) && (LocaleCompare(name,p->name) == 0))
1181 p=(
PolicyInfo *) GetNextValueInLinkedList(policy_cache);
1185 if (p->value != (
char *) NULL)
1186 p->value=DestroyString(p->value);
1190 p=(
PolicyInfo *) AcquireCriticalMemory(
sizeof(*p));
1191 (void) memset(p,0,
sizeof(*p));
1192 p->exempt=MagickFalse;
1193 p->signature=MagickCoreSignature;
1195 p->name=AcquirePolicyString(name,1);
1196 status=AppendValueToLinkedList(policy_cache,p);
1198 p->value=AcquirePolicyString(value,1);
1199 UnlockSemaphoreInfo(policy_semaphore);
1200 if (status == MagickFalse)
1205 MagickExport MagickBooleanType SetMagickSecurityPolicyValue(
1206 const PolicyDomain domain,
const char *name,
const char *value,
1212 magick_unreferenced(exception);
1214 if ((name == (
const char *) NULL) || (value == (
const char *) NULL))
1215 return(MagickFalse);
1218 case CachePolicyDomain:
1220 if (LocaleCompare(name,
"memory-map") == 0)
1222 if (LocaleCompare(value,
"anonymous") != 0)
1223 return(MagickFalse);
1224 ResetCacheAnonymousMemory();
1225 ResetStreamAnonymousMemory();
1226 return(SetPolicyValue(domain,name,value));
1228 if (LocaleCompare(name,
"synchronize") == 0)
1229 return(SetPolicyValue(domain,name,value));
1232 case ResourcePolicyDomain:
1237 if (LocaleCompare(name,
"temporary-path") == 0)
1238 return(SetPolicyValue(domain,name,value));
1239 type=ParseCommandOption(MagickResourceOptions,MagickFalse,name);
1245 limit=MagickResourceInfinity;
1246 if (LocaleCompare(
"unlimited",value) != 0)
1247 limit=StringToMagickSizeType(value,100.0);
1248 return(SetMagickResourceLimit((ResourceType) type,limit));
1252 case SystemPolicyDomain:
1254 if (LocaleCompare(name,
"font") == 0)
1255 return(SetPolicyValue(domain,name,value));
1256 if (LocaleCompare(name,
"max-memory-request") == 0)
1258 current_value=GetPolicyValue(
"system:max-memory-request");
1259 if ((current_value == (
char *) NULL) ||
1260 (StringToSizeType(value,100.0) < StringToSizeType(current_value,100.0)))
1262 if (current_value != (
char *) NULL)
1263 current_value=DestroyString(current_value);
1264 ResetMaxMemoryRequest();
1265 return(SetPolicyValue(domain,name,value));
1267 if (current_value != (
char *) NULL)
1268 current_value=DestroyString(current_value);
1270 if (LocaleCompare(name,
"memory-map") == 0)
1272 if (LocaleCompare(value,
"anonymous") != 0)
1273 return(MagickFalse);
1274 ResetVirtualAnonymousMemory();
1275 return(SetPolicyValue(domain,name,value));
1277 if (LocaleCompare(name,
"precision") == 0)
1279 ResetMagickPrecision();
1280 return(SetPolicyValue(domain,name,value));
1282 if (LocaleCompare(name,
"shred") == 0)
1284 current_value=GetPolicyValue(
"system:shred");
1285 if ((current_value == (
char *) NULL) ||
1286 (StringToInteger(value) > StringToInteger(current_value)))
1288 if (current_value != (
char *) NULL)
1289 current_value=DestroyString(current_value);
1290 return(SetPolicyValue(domain,name,value));
1292 if (current_value != (
char *) NULL)
1293 current_value=DestroyString(current_value);
1297 case CoderPolicyDomain:
1298 case DelegatePolicyDomain:
1299 case FilterPolicyDomain:
1300 case ModulePolicyDomain:
1301 case PathPolicyDomain:
1305 return(MagickFalse);