MagickCore  7.0.3
policy.c
Go to the documentation of this file.
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-2019 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/script/license.php %
26 % %
27 % Unless required by applicable law or agreed to in writing, software %
28 % distributed under the License is distributed on an "AS IS" BASIS, %
29 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30 % See the License for the specific language governing permissions and %
31 % limitations under the License. %
32 % %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 %
35 % We use linked-lists because splay-trees do not currently support duplicate
36 % key / value pairs (.e.g X11 green compliance and SVG green compliance).
37 %
38 */
39 
40 /*
41  Include declarations.
42 */
43 #include "MagickCore/studio.h"
45 #include "MagickCore/client.h"
46 #include "MagickCore/configure.h"
48 #include "MagickCore/exception.h"
51 #include "MagickCore/memory_.h"
53 #include "MagickCore/monitor.h"
55 #include "MagickCore/option.h"
56 #include "MagickCore/policy.h"
58 #include "MagickCore/resource_.h"
60 #include "MagickCore/semaphore.h"
62 #include "MagickCore/string_.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
67 #include "MagickCore/xml-tree.h"
69 
70 /*
71  Define declarations.
72 */
73 #define PolicyFilename "policy.xml"
74 
75 /*
76  Typedef declarations.
77 */
79 {
80  char
81  *path;
82 
85 
88 
89  char
90  *name,
91  *pattern,
92  *value;
93 
96  stealth,
97  debug;
98 
101 
102  size_t
104 };
105 
106 typedef struct _PolicyMapInfo
107 {
108  const PolicyDomain
110 
111  const PolicyRights
113 
114  const char
116  *pattern,
117  *value;
118 } PolicyMapInfo;
119 
120 /*
121  Static declarations.
122 */
123 static const PolicyMapInfo
125  {
126  { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
127  (const char *) NULL, (const char *) NULL }
128  };
129 
130 static LinkedListInfo
132 
133 static SemaphoreInfo
135 
136 /*
137  Forward declarations.
138 */
139 static MagickBooleanType
141  LoadPolicyCache(LinkedListInfo *,const char *,const char *,const size_t,
142  ExceptionInfo *);
143 
144 /*
145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 % %
147 % %
148 % %
149 % A c q u i r e P o l i c y C a c h e %
150 % %
151 % %
152 % %
153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 %
155 % AcquirePolicyCache() caches one or more policy configurations which provides
156 % a mapping between policy attributes and a policy name.
157 %
158 % The format of the AcquirePolicyCache method is:
159 %
160 % LinkedListInfo *AcquirePolicyCache(const char *filename,
161 % ExceptionInfo *exception)
162 %
163 % A description of each parameter follows:
164 %
165 % o filename: the policy configuration file name.
166 %
167 % o exception: return any errors or warnings in this structure.
168 %
169 */
170 static LinkedListInfo *AcquirePolicyCache(const char *filename,
171  ExceptionInfo *exception)
172 {
174  *cache;
175 
177  status;
178 
179  register ssize_t
180  i;
181 
182  /*
183  Load external policy map.
184  */
185  cache=NewLinkedList(0);
186  status=MagickTrue;
187 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
188  status=LoadPolicyCache(cache,ZeroConfigurationPolicy,"[zero-configuration]",0,
189  exception);
190 #else
191  {
192  const StringInfo
193  *option;
194 
196  *options;
197 
198  options=GetConfigureOptions(filename,exception);
199  option=(const StringInfo *) GetNextValueInLinkedList(options);
200  while (option != (const StringInfo *) NULL)
201  {
202  status&=LoadPolicyCache(cache,(const char *) GetStringInfoDatum(option),
203  GetStringInfoPath(option),0,exception);
204  option=(const StringInfo *) GetNextValueInLinkedList(options);
205  }
206  options=DestroyConfigureOptions(options);
207  }
208 #endif
209  /*
210  Load built-in policy map.
211  */
212  for (i=0; i < (ssize_t) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
213  {
214  PolicyInfo
215  *policy_info;
216 
217  register const PolicyMapInfo
218  *p;
219 
220  p=PolicyMap+i;
221  policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
222  if (policy_info == (PolicyInfo *) NULL)
223  {
224  (void) ThrowMagickException(exception,GetMagickModule(),
225  ResourceLimitError,"MemoryAllocationFailed","`%s'",
226  p->name == (char *) NULL ? "" : p->name);
227  continue;
228  }
229  (void) memset(policy_info,0,sizeof(*policy_info));
230  policy_info->path=(char *) "[built-in]";
231  policy_info->domain=p->domain;
232  policy_info->rights=p->rights;
233  policy_info->name=(char *) p->name;
234  policy_info->pattern=(char *) p->pattern;
235  policy_info->value=(char *) p->value;
236  policy_info->exempt=MagickTrue;
237  policy_info->signature=MagickCoreSignature;
238  status&=AppendValueToLinkedList(cache,policy_info);
239  if (status == MagickFalse)
240  (void) ThrowMagickException(exception,GetMagickModule(),
241  ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
242  }
243  return(cache);
244 }
245 
246 /*
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 % %
249 % %
250 % %
251 + G e t P o l i c y I n f o %
252 % %
253 % %
254 % %
255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 %
257 % GetPolicyInfo() searches the policy list for the specified name and if found
258 % returns attributes for that policy.
259 %
260 % The format of the GetPolicyInfo method is:
261 %
262 % PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
263 %
264 % A description of each parameter follows:
265 %
266 % o name: the policy name.
267 %
268 % o exception: return any errors or warnings in this structure.
269 %
270 */
271 static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
272 {
273  char
274  policyname[MagickPathExtent];
275 
277  domain;
278 
279  register PolicyInfo
280  *p;
281 
282  register char
283  *q;
284 
285  assert(exception != (ExceptionInfo *) NULL);
286  if (IsPolicyCacheInstantiated(exception) == MagickFalse)
287  return((PolicyInfo *) NULL);
288  /*
289  Strip names of whitespace.
290  */
291  *policyname='\0';
292  if (name != (const char *) NULL)
293  (void) CopyMagickString(policyname,name,MagickPathExtent);
294  for (q=policyname; *q != '\0'; q++)
295  {
296  if (isspace((int) ((unsigned char) *q)) == 0)
297  continue;
298  (void) CopyMagickString(q,q+1,MagickPathExtent);
299  q--;
300  }
301  /*
302  Strip domain from policy name (e.g. resource:map).
303  */
304  domain=UndefinedPolicyDomain;
305  for (q=policyname; *q != '\0'; q++)
306  {
307  if (*q != ':')
308  continue;
309  *q='\0';
311  MagickTrue,policyname);
312  (void) CopyMagickString(policyname,q+1,MagickPathExtent);
313  break;
314  }
315  /*
316  Search for policy tag.
317  */
321  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
322  {
324  return(p);
325  }
326  while (p != (PolicyInfo *) NULL)
327  {
328  if ((domain == UndefinedPolicyDomain) || (p->domain == domain))
329  if (LocaleCompare(policyname,p->name) == 0)
330  break;
332  }
333  if (p != (PolicyInfo *) NULL)
337  return(p);
338 }
339 
340 /*
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % %
343 % %
344 % %
345 % G e t P o l i c y I n f o L i s t %
346 % %
347 % %
348 % %
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %
351 % GetPolicyInfoList() returns any policies that match the specified pattern.
352 %
353 % The format of the GetPolicyInfoList function is:
354 %
355 % const PolicyInfo **GetPolicyInfoList(const char *pattern,
356 % size_t *number_policies,ExceptionInfo *exception)
357 %
358 % A description of each parameter follows:
359 %
360 % o pattern: Specifies a pointer to a text string containing a pattern.
361 %
362 % o number_policies: returns the number of policies in the list.
363 %
364 % o exception: return any errors or warnings in this structure.
365 %
366 */
367 MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
368  size_t *number_policies,ExceptionInfo *exception)
369 {
370  const PolicyInfo
371  **policies;
372 
373  register const PolicyInfo
374  *p;
375 
376  register ssize_t
377  i;
378 
379  /*
380  Allocate policy list.
381  */
382  assert(pattern != (char *) NULL);
383  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
384  assert(number_policies != (size_t *) NULL);
385  *number_policies=0;
386  p=GetPolicyInfo("*",exception);
387  if (p == (const PolicyInfo *) NULL)
388  return((const PolicyInfo **) NULL);
389  policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
390  GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
391  if (policies == (const PolicyInfo **) NULL)
392  return((const PolicyInfo **) NULL);
393  /*
394  Generate policy list.
395  */
399  for (i=0; p != (const PolicyInfo *) NULL; )
400  {
401  if ((p->stealth == MagickFalse) &&
402  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
403  policies[i++]=p;
405  }
407  policies[i]=(PolicyInfo *) NULL;
408  *number_policies=(size_t) i;
409  return(policies);
410 }
411 
412 /*
413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414 % %
415 % %
416 % %
417 % G e t P o l i c y L i s t %
418 % %
419 % %
420 % %
421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422 %
423 % GetPolicyList() returns any policies that match the specified pattern.
424 %
425 % The format of the GetPolicyList function is:
426 %
427 % char **GetPolicyList(const char *pattern,size_t *number_policies,
428 % ExceptionInfo *exception)
429 %
430 % A description of each parameter follows:
431 %
432 % o pattern: a pointer to a text string containing a pattern.
433 %
434 % o number_policies: returns the number of policies in the list.
435 %
436 % o exception: return any errors or warnings in this structure.
437 %
438 */
439 MagickExport char **GetPolicyList(const char *pattern,
440  size_t *number_policies,ExceptionInfo *exception)
441 {
442  char
443  **policies;
444 
445  register const PolicyInfo
446  *p;
447 
448  register ssize_t
449  i;
450 
451  /*
452  Allocate policy list.
453  */
454  assert(pattern != (char *) NULL);
455  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
456  assert(number_policies != (size_t *) NULL);
457  *number_policies=0;
458  p=GetPolicyInfo("*",exception);
459  if (p == (const PolicyInfo *) NULL)
460  return((char **) NULL);
461  policies=(char **) AcquireQuantumMemory((size_t)
462  GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
463  if (policies == (char **) NULL)
464  return((char **) NULL);
465  /*
466  Generate policy list.
467  */
471  for (i=0; p != (const PolicyInfo *) NULL; )
472  {
473  if ((p->stealth == MagickFalse) &&
474  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
475  policies[i++]=ConstantString(p->name);
477  }
479  policies[i]=(char *) NULL;
480  *number_policies=(size_t) i;
481  return(policies);
482 }
483 
484 /*
485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 % %
487 % %
488 % %
489 % G e t P o l i c y V a l u e %
490 % %
491 % %
492 % %
493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494 %
495 % GetPolicyValue() returns the value associated with the named policy.
496 %
497 % The format of the GetPolicyValue method is:
498 %
499 % char *GetPolicyValue(const char *name)
500 %
501 % A description of each parameter follows:
502 %
503 % o name: The name of the policy.
504 %
505 */
506 MagickExport char *GetPolicyValue(const char *name)
507 {
508  const char
509  *value;
510 
511  const PolicyInfo
512  *policy_info;
513 
515  *exception;
516 
517  assert(name != (const char *) NULL);
518  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
519  exception=AcquireExceptionInfo();
520  policy_info=GetPolicyInfo(name,exception);
521  exception=DestroyExceptionInfo(exception);
522  if (policy_info == (PolicyInfo *) NULL)
523  return((char *) NULL);
524  value=policy_info->value;
525  if ((value == (const char *) NULL) || (*value == '\0'))
526  return((char *) NULL);
527  return(ConstantString(value));
528 }
529 
530 /*
531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532 % %
533 % %
534 % %
535 + 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 %
536 % %
537 % %
538 % %
539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
540 %
541 % IsPolicyCacheInstantiated() determines if the policy list is instantiated.
542 % If not, it instantiates the list and returns it.
543 %
544 % The format of the IsPolicyInstantiated method is:
545 %
546 % MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
547 %
548 % A description of each parameter follows.
549 %
550 % o exception: return any errors or warnings in this structure.
551 %
552 */
554 {
555  if (policy_cache == (LinkedListInfo *) NULL)
556  {
557  if (policy_semaphore == (SemaphoreInfo *) NULL)
560  if (policy_cache == (LinkedListInfo *) NULL)
563  }
564  return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
565 }
566 
567 /*
568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569 % %
570 % %
571 % %
572 % I s R i g h t s A u t h o r i z e d %
573 % %
574 % %
575 % %
576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577 %
578 % IsRightsAuthorized() returns MagickTrue if the policy authorizes the
579 % requested rights for the specified domain.
580 %
581 % The format of the IsRightsAuthorized method is:
582 %
583 % MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
584 % const PolicyRights rights,const char *pattern)
585 %
586 % A description of each parameter follows:
587 %
588 % o domain: the policy domain.
589 %
590 % o rights: the policy rights.
591 %
592 % o pattern: the coder, delegate, filter, or path pattern.
593 %
594 */
596  const PolicyRights rights,const char *pattern)
597 {
598  const PolicyInfo
599  *policy_info;
600 
602  *exception;
603 
605  authorized;
606 
607  register PolicyInfo
608  *p;
609 
610  if (IsEventLogging() != MagickFalse)
612  "Domain: %s; rights=%s; pattern=\"%s\" ...",
615  exception=AcquireExceptionInfo();
616  policy_info=GetPolicyInfo("*",exception);
617  exception=DestroyExceptionInfo(exception);
618  if (policy_info == (PolicyInfo *) NULL)
619  return(MagickTrue);
620  authorized=MagickTrue;
624  while (p != (PolicyInfo *) NULL)
625  {
626  if ((p->domain == domain) &&
628  {
629  if ((rights & ReadPolicyRights) != 0)
630  authorized=(p->rights & ReadPolicyRights) != 0 ? MagickTrue :
631  MagickFalse;
632  if ((rights & WritePolicyRights) != 0)
633  authorized=(p->rights & WritePolicyRights) != 0 ? MagickTrue :
634  MagickFalse;
635  if ((rights & ExecutePolicyRights) != 0)
636  authorized=(p->rights & ExecutePolicyRights) != 0 ? MagickTrue :
637  MagickFalse;
638  }
640  }
642  return(authorized);
643 }
644 
645 /*
646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
647 % %
648 % %
649 % %
650 % L i s t P o l i c y I n f o %
651 % %
652 % %
653 % %
654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655 %
656 % ListPolicyInfo() lists policies to the specified file.
657 %
658 % The format of the ListPolicyInfo method is:
659 %
660 % MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
661 %
662 % A description of each parameter follows.
663 %
664 % o file: List policy names to this file handle.
665 %
666 % o exception: return any errors or warnings in this structure.
667 %
668 */
670  ExceptionInfo *exception)
671 {
672  const char
673  *path,
674  *domain;
675 
676  const PolicyInfo
677  **policy_info;
678 
679  register ssize_t
680  i;
681 
682  size_t
683  number_policies;
684 
685  /*
686  List name and attributes of each policy in the list.
687  */
688  if (file == (const FILE *) NULL)
689  file=stdout;
690  policy_info=GetPolicyInfoList("*",&number_policies,exception);
691  if (policy_info == (const PolicyInfo **) NULL)
692  return(MagickFalse);
693  path=(const char *) NULL;
694  for (i=0; i < (ssize_t) number_policies; i++)
695  {
696  if (policy_info[i]->stealth != MagickFalse)
697  continue;
698  if (((path == (const char *) NULL) ||
699  (LocaleCompare(path,policy_info[i]->path) != 0)) &&
700  (policy_info[i]->path != (char *) NULL))
701  (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
702  path=policy_info[i]->path;
704  policy_info[i]->domain);
705  (void) FormatLocaleFile(file," Policy: %s\n",domain);
706  if ((policy_info[i]->domain == CachePolicyDomain) ||
707  (policy_info[i]->domain == ResourcePolicyDomain) ||
708  (policy_info[i]->domain == SystemPolicyDomain))
709  {
710  if (policy_info[i]->name != (char *) NULL)
711  (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
712  if (policy_info[i]->value != (char *) NULL)
713  (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
714  }
715  else
716  {
717  (void) FormatLocaleFile(file," rights: ");
718  if (policy_info[i]->rights == NoPolicyRights)
719  (void) FormatLocaleFile(file,"None ");
720  if ((policy_info[i]->rights & ReadPolicyRights) != 0)
721  (void) FormatLocaleFile(file,"Read ");
722  if ((policy_info[i]->rights & WritePolicyRights) != 0)
723  (void) FormatLocaleFile(file,"Write ");
724  if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
725  (void) FormatLocaleFile(file,"Execute ");
726  (void) FormatLocaleFile(file,"\n");
727  if (policy_info[i]->pattern != (char *) NULL)
728  (void) FormatLocaleFile(file," pattern: %s\n",
729  policy_info[i]->pattern);
730  }
731  }
732  policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
733  policy_info);
734  (void) fflush(file);
735  return(MagickTrue);
736 }
737 
738 /*
739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
740 % %
741 % %
742 % %
743 + L o a d P o l i c y C a c h e %
744 % %
745 % %
746 % %
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748 %
749 % LoadPolicyCache() loads the policy configurations which provides a mapping
750 % between policy attributes and a policy domain.
751 %
752 % The format of the LoadPolicyCache method is:
753 %
754 % MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
755 % const char *filename,const size_t depth,ExceptionInfo *exception)
756 %
757 % A description of each parameter follows:
758 %
759 % o xml: The policy list in XML format.
760 %
761 % o filename: The policy list filename.
762 %
763 % o depth: depth of <include /> statements.
764 %
765 % o exception: return any errors or warnings in this structure.
766 %
767 */
768 static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
769  const char *filename,const size_t depth,ExceptionInfo *exception)
770 {
771  char
772  keyword[MagickPathExtent],
773  *token;
774 
775  const char
776  *q;
777 
779  status;
780 
781  PolicyInfo
782  *policy_info;
783 
784  size_t
785  extent;
786 
787  /*
788  Load the policy map file.
789  */
791  "Loading policy file \"%s\" ...",filename);
792  if (xml == (char *) NULL)
793  return(MagickFalse);
794  status=MagickTrue;
795  policy_info=(PolicyInfo *) NULL;
796  token=AcquireString(xml);
797  extent=strlen(token)+MagickPathExtent;
798  for (q=(const char *) xml; *q != '\0'; )
799  {
800  /*
801  Interpret XML.
802  */
803  (void) GetNextToken(q,&q,extent,token);
804  if (*token == '\0')
805  break;
806  (void) CopyMagickString(keyword,token,MagickPathExtent);
807  if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
808  {
809  /*
810  Docdomain element.
811  */
812  while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
813  (void) GetNextToken(q,&q,extent,token);
814  continue;
815  }
816  if (LocaleNCompare(keyword,"<!--",4) == 0)
817  {
818  /*
819  Comment element.
820  */
821  while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
822  (void) GetNextToken(q,&q,extent,token);
823  continue;
824  }
825  if (LocaleCompare(keyword,"<include") == 0)
826  {
827  /*
828  Include element.
829  */
830  while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
831  {
832  (void) CopyMagickString(keyword,token,MagickPathExtent);
833  (void) GetNextToken(q,&q,extent,token);
834  if (*token != '=')
835  continue;
836  (void) GetNextToken(q,&q,extent,token);
837  if (LocaleCompare(keyword,"file") == 0)
838  {
839  if (depth > MagickMaxRecursionDepth)
840  (void) ThrowMagickException(exception,GetMagickModule(),
841  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
842  else
843  {
844  char
845  path[MagickPathExtent],
846  *file_xml;
847 
848  GetPathComponent(filename,HeadPath,path);
849  if (*path != '\0')
852  if (*token == *DirectorySeparator)
853  (void) CopyMagickString(path,token,MagickPathExtent);
854  else
855  (void) ConcatenateMagickString(path,token,MagickPathExtent);
856  file_xml=FileToXML(path,~0UL);
857  if (file_xml != (char *) NULL)
858  {
859  status&=LoadPolicyCache(cache,file_xml,path,
860  depth+1,exception);
861  file_xml=DestroyString(file_xml);
862  }
863  }
864  }
865  }
866  continue;
867  }
868  if (LocaleCompare(keyword,"<policy") == 0)
869  {
870  /*
871  Policy element.
872  */
873  policy_info=(PolicyInfo *) AcquireCriticalMemory(sizeof(*policy_info));
874  (void) memset(policy_info,0,sizeof(*policy_info));
875  policy_info->path=ConstantString(filename);
876  policy_info->exempt=MagickFalse;
877  policy_info->signature=MagickCoreSignature;
878  continue;
879  }
880  if (policy_info == (PolicyInfo *) NULL)
881  continue;
882  if ((LocaleCompare(keyword,"/>") == 0) ||
883  (LocaleCompare(keyword,"</policy>") == 0))
884  {
885  status=AppendValueToLinkedList(cache,policy_info);
886  if (status == MagickFalse)
887  (void) ThrowMagickException(exception,GetMagickModule(),
888  ResourceLimitError,"MemoryAllocationFailed","`%s'",
889  policy_info->name);
890  policy_info=(PolicyInfo *) NULL;
891  continue;
892  }
893  (void) GetNextToken(q,(const char **) NULL,extent,token);
894  if (*token != '=')
895  continue;
896  (void) GetNextToken(q,&q,extent,token);
897  (void) GetNextToken(q,&q,extent,token);
898  switch (*keyword)
899  {
900  case 'D':
901  case 'd':
902  {
903  if (LocaleCompare((char *) keyword,"domain") == 0)
904  {
905  policy_info->domain=(PolicyDomain) ParseCommandOption(
907  break;
908  }
909  break;
910  }
911  case 'N':
912  case 'n':
913  {
914  if (LocaleCompare((char *) keyword,"name") == 0)
915  {
916  policy_info->name=ConstantString(token);
917  break;
918  }
919  break;
920  }
921  case 'P':
922  case 'p':
923  {
924  if (LocaleCompare((char *) keyword,"pattern") == 0)
925  {
926  policy_info->pattern=ConstantString(token);
927  break;
928  }
929  break;
930  }
931  case 'R':
932  case 'r':
933  {
934  if (LocaleCompare((char *) keyword,"rights") == 0)
935  {
936  policy_info->rights=(PolicyRights) ParseCommandOption(
938  break;
939  }
940  break;
941  }
942  case 'S':
943  case 's':
944  {
945  if (LocaleCompare((char *) keyword,"stealth") == 0)
946  {
947  policy_info->stealth=IsStringTrue(token);
948  break;
949  }
950  break;
951  }
952  case 'V':
953  case 'v':
954  {
955  if (LocaleCompare((char *) keyword,"value") == 0)
956  {
957  policy_info->value=ConstantString(token);
958  break;
959  }
960  break;
961  }
962  default:
963  break;
964  }
965  }
966  token=(char *) RelinquishMagickMemory(token);
967  return(status != 0 ? MagickTrue : MagickFalse);
968 }
969 
970 /*
971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972 % %
973 % %
974 % %
975 + P o l i c y C o m p o n e n t G e n e s i s %
976 % %
977 % %
978 % %
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 %
981 % PolicyComponentGenesis() instantiates the policy component.
982 %
983 % The format of the PolicyComponentGenesis method is:
984 %
985 % MagickBooleanType PolicyComponentGenesis(void)
986 %
987 */
989 {
990  if (policy_semaphore == (SemaphoreInfo *) NULL)
992  return(MagickTrue);
993 }
994 
995 /*
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 % %
998 % %
999 % %
1000 + P o l i c y C o m p o n e n t T e r m i n u s %
1001 % %
1002 % %
1003 % %
1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005 %
1006 % PolicyComponentTerminus() destroys the policy component.
1007 %
1008 % The format of the PolicyComponentTerminus method is:
1009 %
1010 % PolicyComponentTerminus(void)
1011 %
1012 */
1013 
1014 static void *DestroyPolicyElement(void *policy_info)
1015 {
1016  register PolicyInfo
1017  *p;
1018 
1019  p=(PolicyInfo *) policy_info;
1020  if (p->exempt == MagickFalse)
1021  {
1022  if (p->value != (char *) NULL)
1023  p->value=DestroyString(p->value);
1024  if (p->pattern != (char *) NULL)
1025  p->pattern=DestroyString(p->pattern);
1026  if (p->name != (char *) NULL)
1027  p->name=DestroyString(p->name);
1028  if (p->path != (char *) NULL)
1029  p->path=DestroyString(p->path);
1030  }
1032  return((void *) NULL);
1033 }
1034 
1036 {
1037  if (policy_semaphore == (SemaphoreInfo *) NULL)
1040  if (policy_cache != (LinkedListInfo *) NULL)
1044 }
1045 
1046 /*
1047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1048 % %
1049 % %
1050 % %
1051 % S e t M a g i c k S e c u r i t y P o l i c y %
1052 % %
1053 % %
1054 % %
1055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1056 %
1057 % SetMagickSecurityPolicy() sets the ImageMagick security policy. It returns
1058 % MagickFalse if the policy is already set or if the policy does not parse.
1059 %
1060 % The format of the SetMagickSecurityPolicy method is:
1061 %
1062 % MagickBooleanType SetMagickSecurityPolicy(const char *policy,
1063 % ExceptionInfo *exception)
1064 %
1065 % A description of each parameter follows:
1066 %
1067 % o policy: the security policy in the XML format.
1068 %
1069 % o exception: return any errors or warnings in this structure.
1070 %
1071 */
1073  ExceptionInfo *exception)
1074 {
1075  PolicyInfo
1076  *p;
1077 
1079  status;
1080 
1081  assert(exception != (ExceptionInfo *) NULL);
1082  if (policy == (const char *) NULL)
1083  return(MagickFalse);
1084  if (IsPolicyCacheInstantiated(exception) == MagickFalse)
1085  return(MagickFalse);
1089  if ((p != (PolicyInfo *) NULL) && (p->domain != UndefinedPolicyDomain))
1090  {
1092  return(MagickFalse);
1093  }
1095  status=LoadPolicyCache(policy_cache,policy,"[user-policy]",0,exception);
1096  if (status == MagickFalse)
1097  return(MagickFalse);
1098  return(ResourceComponentGenesis());
1099 }
1100 
1101 /*
1102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103 % %
1104 % %
1105 % %
1106 % 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 %
1107 % %
1108 % %
1109 % %
1110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 %
1112 % SetMagickSecurityPolicyValue() sets a value associated with an ImageMagick
1113 % security policy. For most policies, the value must be less than any value
1114 % set by the security policy configuration file (i.e. policy.xml). It returns
1115 % MagickFalse if the policy cannot be modified or if the policy does not parse.
1116 %
1117 % The format of the SetMagickSecurityPolicyValue method is:
1118 %
1119 % MagickBooleanType SetMagickSecurityPolicyValue(
1120 % const PolicyDomain domain,const char *name,const char *value,
1121 % ExceptionInfo *exception)
1122 %
1123 % A description of each parameter follows:
1124 %
1125 % o domain: the domain of the policy (e.g. system, resource).
1126 %
1127 % o name: the name of the policy.
1128 %
1129 % o value: the value to set the policy to.
1130 %
1131 % o exception: return any errors or warnings in this structure.
1132 %
1133 */
1134 
1136  const char *name,const char *value)
1137 {
1139  status;
1140 
1141  register PolicyInfo
1142  *p;
1143 
1144  status=MagickTrue;
1148  while (p != (PolicyInfo *) NULL)
1149  {
1150  if ((p->domain == domain) && (LocaleCompare(name,p->name) == 0))
1151  break;
1153  }
1154  if (p != (PolicyInfo *) NULL)
1155  {
1156  if (p->value != (char *) NULL)
1157  p->value=DestroyString(p->value);
1158  }
1159  else
1160  {
1161  p=(PolicyInfo *) AcquireCriticalMemory(sizeof(*p));
1162  (void) memset(p,0,sizeof(*p));
1163  p->exempt=MagickFalse;
1165  p->domain=domain;
1166  p->name=ConstantString(name);
1168  }
1169  p->value=ConstantString(value);
1171  if (status == MagickFalse)
1173  return(status);
1174 }
1175 
1177  const PolicyDomain domain,const char *name,const char *value,
1178  ExceptionInfo *exception)
1179 {
1180  char
1181  *current_value;
1182 
1183  magick_unreferenced(exception);
1184  assert(exception != (ExceptionInfo *) NULL);
1185  if ((name == (const char *) NULL) || (value == (const char *) NULL))
1186  return(MagickFalse);
1187  switch(domain)
1188  {
1189  case CachePolicyDomain:
1190  {
1191  if (LocaleCompare(name,"memory-map") == 0)
1192  {
1193  if (LocaleCompare(value,"anonymous") != 0)
1194  return(MagickFalse);
1197  return(SetPolicyValue(domain,name,value));
1198  }
1199  if (LocaleCompare(name,"synchronize") == 0)
1200  return(SetPolicyValue(domain,name,value));
1201  break;
1202  }
1203  case ResourcePolicyDomain:
1204  {
1205  ssize_t
1206  type;
1207 
1208  if (LocaleCompare(name,"temporary-path") == 0)
1209  return(SetPolicyValue(domain,name,value));
1211  if (type >= 0)
1212  {
1214  limit;
1215 
1216  limit=MagickResourceInfinity;
1217  if (LocaleCompare("unlimited",value) != 0)
1218  limit=StringToMagickSizeType(value,100.0);
1219  return(SetMagickResourceLimit((ResourceType) type,limit));
1220  }
1221  break;
1222  }
1223  case SystemPolicyDomain:
1224  {
1225  if (LocaleCompare(name,"max-memory-request") == 0)
1226  {
1227  current_value=GetPolicyValue("system:max-memory-request");
1228  if ((current_value == (char *) NULL) ||
1229  (StringToSizeType(value,100.0) < StringToSizeType(current_value,100.0)))
1230  {
1232  return(SetPolicyValue(domain,name,value));
1233  }
1234  }
1235  if (LocaleCompare(name,"memory-map") == 0)
1236  {
1237  if (LocaleCompare(value,"anonymous") != 0)
1238  return(MagickFalse);
1240  return(SetPolicyValue(domain,name,value));
1241  }
1242  if (LocaleCompare(name,"precision") == 0)
1243  {
1245  return(SetPolicyValue(domain,name,value));
1246  }
1247  if (LocaleCompare(name,"shred") == 0)
1248  {
1249  current_value=GetPolicyValue("system:shred");
1250  if ((current_value == (char *) NULL) ||
1251  (StringToInteger(value) > StringToInteger(current_value)))
1252  return(SetPolicyValue(domain,name,value));
1253  }
1254  break;
1255  }
1256  case CoderPolicyDomain:
1257  case DelegatePolicyDomain:
1258  case FilterPolicyDomain:
1259  case ModulePolicyDomain:
1260  case PathPolicyDomain:
1261  default:
1262  break;
1263  }
1264  return(MagickFalse);
1265 }
MagickBooleanType stealth
Definition: policy.c:95
char * value
Definition: policy.c:90
MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
Definition: resource.c:1140
#define MagickMaxRecursionDepth
Definition: studio.h:344
static size_t StringToSizeType(const char *string, const double interval)
MagickExport const PolicyInfo ** GetPolicyInfoList(const char *pattern, size_t *number_policies, ExceptionInfo *exception)
Definition: policy.c:367
MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain, const PolicyRights rights, const char *pattern)
Definition: policy.c:595
MagickPrivate MagickBooleanType PolicyComponentGenesis(void)
Definition: policy.c:988
MagickExport MagickBooleanType ListPolicyInfo(FILE *file, ExceptionInfo *exception)
Definition: policy.c:669
MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:450
MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
Definition: linked-list.c:959
MagickExport ssize_t ParseCommandOption(const CommandOption option, const MagickBooleanType list, const char *options)
Definition: option.c:2972
static SemaphoreInfo * policy_semaphore
Definition: policy.c:134
MagickPrivate void PolicyComponentTerminus(void)
Definition: policy.c:1035
SemaphoreInfo * semaphore
Definition: policy.c:100
PolicyRights
Definition: policy.h:41
static int StringToInteger(const char *magick_restrict value)
MagickExport LinkedListInfo * DestroyLinkedList(LinkedListInfo *list_info, void *(*relinquish_value)(void *))
Definition: linked-list.c:219
struct _PolicyMapInfo PolicyMapInfo
char * name
Definition: policy.c:90
MagickBooleanType debug
Definition: policy.c:95
MagickExport size_t ConcatenateMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:426
MagickExport SemaphoreInfo * AcquireSemaphoreInfo(void)
Definition: semaphore.c:192
MagickExport MagickBooleanType InsertValueInLinkedList(LinkedListInfo *list_info, const size_t index, const void *value)
Definition: linked-list.c:447
const char * name
Definition: policy.c:115
char * pattern
Definition: policy.c:90
MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type, const MagickSizeType limit)
Definition: resource.c:1346
static PolicyInfo * GetPolicyInfo(const char *name, ExceptionInfo *exception)
Definition: policy.c:271
MagickExport ExceptionInfo * AcquireExceptionInfo(void)
Definition: exception.c:115
MagickExport MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info, const void *value)
Definition: linked-list.c:111
static void * AcquireCriticalMemory(const size_t size)
MagickExport void * RemoveElementByValueFromLinkedList(LinkedListInfo *list_info, const void *value)
Definition: linked-list.c:756
static LinkedListInfo * policy_cache
Definition: policy.c:131
MagickExport MagickBooleanType SetMagickSecurityPolicyValue(const PolicyDomain domain, const char *name, const char *value, ExceptionInfo *exception)
Definition: policy.c:1176
MagickExport size_t GetNextToken(const char *start, const char **end, const size_t extent, char *token)
Definition: token.c:173
Definition: log.h:52
static const PolicyMapInfo PolicyMap[]
Definition: policy.c:124
MagickExport void * GetNextValueInLinkedList(LinkedListInfo *list_info)
Definition: linked-list.c:305
size_t signature
Definition: policy.c:103
#define MagickCoreSignature
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:293
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1215
MagickExport LinkedListInfo * GetConfigureOptions(const char *filename, ExceptionInfo *exception)
Definition: configure.c:639
static MagickBooleanType LoadPolicyCache(LinkedListInfo *, const char *, const char *, const size_t, ExceptionInfo *)
Definition: policy.c:768
MagickExport void GetPathComponent(const char *path, PathType type, char *component)
Definition: utility.c:1213
MagickExport ssize_t FormatLocaleFile(FILE *file, const char *magick_restrict format,...)
Definition: locale.c:404
MagickBooleanType
Definition: magick-type.h:158
#define DirectorySeparator
Definition: studio.h:259
unsigned int MagickStatusType
Definition: magick-type.h:121
MagickExport char * AcquireString(const char *source)
Definition: string.c:129
MagickPrivate void ResetMagickPrecision(void)
Definition: magick.c:1736
MagickExport const char * CommandOptionToMnemonic(const CommandOption option, const ssize_t type)
Definition: option.c:2681
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:543
MagickExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition: locale.c:1570
MagickExport MagickBooleanType GlobExpression(const char *expression, const char *pattern, const MagickBooleanType case_insensitive)
Definition: token.c:352
size_t MagickSizeType
Definition: magick-type.h:130
#define MagickPathExtent
MagickExport MagickBooleanType IsStringTrue(const char *value)
Definition: string.c:1425
MagickExport MagickBooleanType IsEventLogging(void)
Definition: log.c:720
static MagickBooleanType SetPolicyValue(const PolicyDomain domain, const char *name, const char *value)
Definition: policy.c:1135
PolicyRights rights
Definition: policy.c:87
MagickExport char ** GetPolicyList(const char *pattern, size_t *number_policies, ExceptionInfo *exception)
Definition: policy.c:439
MagickPrivate void ResetCacheAnonymousMemory(void)
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1145
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1413
MagickExport LinkedListInfo * NewLinkedList(const size_t capacity)
Definition: linked-list.c:713
MagickPrivate void ResetStreamAnonymousMemory(void)
MagickExport size_t CopyMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:755
PolicyDomain
Definition: policy.h:28
ResourceType
Definition: resource_.h:25
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1435
#define GetMagickModule()
Definition: log.h:28
MagickExport const char * GetStringInfoPath(const StringInfo *string_info)
Definition: string.c:1302
MagickBooleanType exempt
Definition: policy.c:95
#define PolicyFilename
Definition: policy.c:73
#define MagickResourceInfinity
Definition: resource_.h:41
MagickExport MagickBooleanType SetMagickSecurityPolicy(const char *policy, ExceptionInfo *exception)
Definition: policy.c:1072
MagickExport char * DestroyString(char *string)
Definition: string.c:823
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:472
MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:97
const char * pattern
Definition: policy.c:115
MagickExport size_t GetNumberOfElementsInLinkedList(const LinkedListInfo *list_info)
Definition: linked-list.c:348
static MagickSizeType StringToMagickSizeType(const char *string, const double interval)
static LinkedListInfo * AcquirePolicyCache(const char *filename, ExceptionInfo *exception)
Definition: policy.c:170
MagickExport char * GetPolicyValue(const char *name)
Definition: policy.c:506
const PolicyDomain domain
Definition: policy.c:109
PolicyDomain domain
Definition: policy.c:84
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1069
#define magick_unreferenced(x)
const PolicyRights rights
Definition: policy.c:112
#define MagickPrivate
MagickPrivate char * FileToXML(const char *, const size_t)
Definition: xml-tree.c:599
#define MagickExport
const char * value
Definition: policy.c:115
static void * DestroyPolicyElement(void *policy_info)
Definition: policy.c:1014
MagickPrivate void ResetMaxMemoryRequest(void)
char * path
Definition: policy.c:81
MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:351
MagickExport LinkedListInfo * DestroyConfigureOptions(LinkedListInfo *options)
Definition: configure.c:311
MagickExport char * ConstantString(const char *source)
Definition: string.c:700
MagickPrivate void ResetVirtualAnonymousMemory(void)
Definition: memory.c:1242
MagickExport ExceptionInfo * DestroyExceptionInfo(ExceptionInfo *exception)
Definition: exception.c:418
static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *)
Definition: policy.c:553