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 
611  "Domain: %s; rights=%s; pattern=\"%s\" ...",
614  exception=AcquireExceptionInfo();
615  policy_info=GetPolicyInfo("*",exception);
616  exception=DestroyExceptionInfo(exception);
617  if (policy_info == (PolicyInfo *) NULL)
618  return(MagickTrue);
619  authorized=MagickTrue;
623  while (p != (PolicyInfo *) NULL)
624  {
625  if ((p->domain == domain) &&
627  {
628  if ((rights & ReadPolicyRights) != 0)
629  authorized=(p->rights & ReadPolicyRights) != 0 ? MagickTrue :
630  MagickFalse;
631  if ((rights & WritePolicyRights) != 0)
632  authorized=(p->rights & WritePolicyRights) != 0 ? MagickTrue :
633  MagickFalse;
634  if ((rights & ExecutePolicyRights) != 0)
635  authorized=(p->rights & ExecutePolicyRights) != 0 ? MagickTrue :
636  MagickFalse;
637  }
639  }
641  return(authorized);
642 }
643 
644 /*
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 % %
647 % %
648 % %
649 % L i s t P o l i c y I n f o %
650 % %
651 % %
652 % %
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 %
655 % ListPolicyInfo() lists policies to the specified file.
656 %
657 % The format of the ListPolicyInfo method is:
658 %
659 % MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
660 %
661 % A description of each parameter follows.
662 %
663 % o file: List policy names to this file handle.
664 %
665 % o exception: return any errors or warnings in this structure.
666 %
667 */
669  ExceptionInfo *exception)
670 {
671  const char
672  *path,
673  *domain;
674 
675  const PolicyInfo
676  **policy_info;
677 
678  register ssize_t
679  i;
680 
681  size_t
682  number_policies;
683 
684  /*
685  List name and attributes of each policy in the list.
686  */
687  if (file == (const FILE *) NULL)
688  file=stdout;
689  policy_info=GetPolicyInfoList("*",&number_policies,exception);
690  if (policy_info == (const PolicyInfo **) NULL)
691  return(MagickFalse);
692  path=(const char *) NULL;
693  for (i=0; i < (ssize_t) number_policies; i++)
694  {
695  if (policy_info[i]->stealth != MagickFalse)
696  continue;
697  if (((path == (const char *) NULL) ||
698  (LocaleCompare(path,policy_info[i]->path) != 0)) &&
699  (policy_info[i]->path != (char *) NULL))
700  (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
701  path=policy_info[i]->path;
703  policy_info[i]->domain);
704  (void) FormatLocaleFile(file," Policy: %s\n",domain);
705  if ((policy_info[i]->domain == CachePolicyDomain) ||
706  (policy_info[i]->domain == ResourcePolicyDomain) ||
707  (policy_info[i]->domain == SystemPolicyDomain))
708  {
709  if (policy_info[i]->name != (char *) NULL)
710  (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
711  if (policy_info[i]->value != (char *) NULL)
712  (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
713  }
714  else
715  {
716  (void) FormatLocaleFile(file," rights: ");
717  if (policy_info[i]->rights == NoPolicyRights)
718  (void) FormatLocaleFile(file,"None ");
719  if ((policy_info[i]->rights & ReadPolicyRights) != 0)
720  (void) FormatLocaleFile(file,"Read ");
721  if ((policy_info[i]->rights & WritePolicyRights) != 0)
722  (void) FormatLocaleFile(file,"Write ");
723  if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
724  (void) FormatLocaleFile(file,"Execute ");
725  (void) FormatLocaleFile(file,"\n");
726  if (policy_info[i]->pattern != (char *) NULL)
727  (void) FormatLocaleFile(file," pattern: %s\n",
728  policy_info[i]->pattern);
729  }
730  }
731  policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
732  policy_info);
733  (void) fflush(file);
734  return(MagickTrue);
735 }
736 
737 /*
738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
739 % %
740 % %
741 % %
742 + L o a d P o l i c y C a c h e %
743 % %
744 % %
745 % %
746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
747 %
748 % LoadPolicyCache() loads the policy configurations which provides a mapping
749 % between policy attributes and a policy domain.
750 %
751 % The format of the LoadPolicyCache method is:
752 %
753 % MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
754 % const char *filename,const size_t depth,ExceptionInfo *exception)
755 %
756 % A description of each parameter follows:
757 %
758 % o xml: The policy list in XML format.
759 %
760 % o filename: The policy list filename.
761 %
762 % o depth: depth of <include /> statements.
763 %
764 % o exception: return any errors or warnings in this structure.
765 %
766 */
767 static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
768  const char *filename,const size_t depth,ExceptionInfo *exception)
769 {
770  char
771  keyword[MagickPathExtent],
772  *token;
773 
774  const char
775  *q;
776 
778  status;
779 
780  PolicyInfo
781  *policy_info;
782 
783  size_t
784  extent;
785 
786  /*
787  Load the policy map file.
788  */
790  "Loading policy file \"%s\" ...",filename);
791  if (xml == (char *) NULL)
792  return(MagickFalse);
793  status=MagickTrue;
794  policy_info=(PolicyInfo *) NULL;
795  token=AcquireString(xml);
796  extent=strlen(token)+MagickPathExtent;
797  for (q=(const char *) xml; *q != '\0'; )
798  {
799  /*
800  Interpret XML.
801  */
802  GetNextToken(q,&q,extent,token);
803  if (*token == '\0')
804  break;
805  (void) CopyMagickString(keyword,token,MagickPathExtent);
806  if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
807  {
808  /*
809  Docdomain element.
810  */
811  while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
812  GetNextToken(q,&q,extent,token);
813  continue;
814  }
815  if (LocaleNCompare(keyword,"<!--",4) == 0)
816  {
817  /*
818  Comment element.
819  */
820  while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
821  GetNextToken(q,&q,extent,token);
822  continue;
823  }
824  if (LocaleCompare(keyword,"<include") == 0)
825  {
826  /*
827  Include element.
828  */
829  while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
830  {
831  (void) CopyMagickString(keyword,token,MagickPathExtent);
832  GetNextToken(q,&q,extent,token);
833  if (*token != '=')
834  continue;
835  GetNextToken(q,&q,extent,token);
836  if (LocaleCompare(keyword,"file") == 0)
837  {
838  if (depth > MagickMaxRecursionDepth)
839  (void) ThrowMagickException(exception,GetMagickModule(),
840  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
841  else
842  {
843  char
844  path[MagickPathExtent],
845  *file_xml;
846 
847  GetPathComponent(filename,HeadPath,path);
848  if (*path != '\0')
851  if (*token == *DirectorySeparator)
852  (void) CopyMagickString(path,token,MagickPathExtent);
853  else
854  (void) ConcatenateMagickString(path,token,MagickPathExtent);
855  file_xml=FileToXML(path,~0UL);
856  if (file_xml != (char *) NULL)
857  {
858  status&=LoadPolicyCache(cache,file_xml,path,
859  depth+1,exception);
860  file_xml=DestroyString(file_xml);
861  }
862  }
863  }
864  }
865  continue;
866  }
867  if (LocaleCompare(keyword,"<policy") == 0)
868  {
869  /*
870  Policy element.
871  */
872  policy_info=(PolicyInfo *) AcquireCriticalMemory(sizeof(*policy_info));
873  (void) memset(policy_info,0,sizeof(*policy_info));
874  policy_info->path=ConstantString(filename);
875  policy_info->exempt=MagickFalse;
876  policy_info->signature=MagickCoreSignature;
877  continue;
878  }
879  if (policy_info == (PolicyInfo *) NULL)
880  continue;
881  if ((LocaleCompare(keyword,"/>") == 0) ||
882  (LocaleCompare(keyword,"</policy>") == 0))
883  {
884  status=AppendValueToLinkedList(cache,policy_info);
885  if (status == MagickFalse)
886  (void) ThrowMagickException(exception,GetMagickModule(),
887  ResourceLimitError,"MemoryAllocationFailed","`%s'",
888  policy_info->name);
889  policy_info=(PolicyInfo *) NULL;
890  continue;
891  }
892  GetNextToken(q,(const char **) NULL,extent,token);
893  if (*token != '=')
894  continue;
895  GetNextToken(q,&q,extent,token);
896  GetNextToken(q,&q,extent,token);
897  switch (*keyword)
898  {
899  case 'D':
900  case 'd':
901  {
902  if (LocaleCompare((char *) keyword,"domain") == 0)
903  {
904  policy_info->domain=(PolicyDomain) ParseCommandOption(
906  break;
907  }
908  break;
909  }
910  case 'N':
911  case 'n':
912  {
913  if (LocaleCompare((char *) keyword,"name") == 0)
914  {
915  policy_info->name=ConstantString(token);
916  break;
917  }
918  break;
919  }
920  case 'P':
921  case 'p':
922  {
923  if (LocaleCompare((char *) keyword,"pattern") == 0)
924  {
925  policy_info->pattern=ConstantString(token);
926  break;
927  }
928  break;
929  }
930  case 'R':
931  case 'r':
932  {
933  if (LocaleCompare((char *) keyword,"rights") == 0)
934  {
935  policy_info->rights=(PolicyRights) ParseCommandOption(
937  break;
938  }
939  break;
940  }
941  case 'S':
942  case 's':
943  {
944  if (LocaleCompare((char *) keyword,"stealth") == 0)
945  {
946  policy_info->stealth=IsStringTrue(token);
947  break;
948  }
949  break;
950  }
951  case 'V':
952  case 'v':
953  {
954  if (LocaleCompare((char *) keyword,"value") == 0)
955  {
956  policy_info->value=ConstantString(token);
957  break;
958  }
959  break;
960  }
961  default:
962  break;
963  }
964  }
965  token=(char *) RelinquishMagickMemory(token);
966  return(status != 0 ? MagickTrue : MagickFalse);
967 }
968 
969 /*
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 % %
972 % %
973 % %
974 + P o l i c y C o m p o n e n t G e n e s i s %
975 % %
976 % %
977 % %
978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979 %
980 % PolicyComponentGenesis() instantiates the policy component.
981 %
982 % The format of the PolicyComponentGenesis method is:
983 %
984 % MagickBooleanType PolicyComponentGenesis(void)
985 %
986 */
988 {
989  if (policy_semaphore == (SemaphoreInfo *) NULL)
991  return(MagickTrue);
992 }
993 
994 /*
995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996 % %
997 % %
998 % %
999 + P o l i c y C o m p o n e n t T e r m i n u s %
1000 % %
1001 % %
1002 % %
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %
1005 % PolicyComponentTerminus() destroys the policy component.
1006 %
1007 % The format of the PolicyComponentTerminus method is:
1008 %
1009 % PolicyComponentTerminus(void)
1010 %
1011 */
1012 
1013 static void *DestroyPolicyElement(void *policy_info)
1014 {
1015  register PolicyInfo
1016  *p;
1017 
1018  p=(PolicyInfo *) policy_info;
1019  if (p->exempt == MagickFalse)
1020  {
1021  if (p->value != (char *) NULL)
1022  p->value=DestroyString(p->value);
1023  if (p->pattern != (char *) NULL)
1024  p->pattern=DestroyString(p->pattern);
1025  if (p->name != (char *) NULL)
1026  p->name=DestroyString(p->name);
1027  if (p->path != (char *) NULL)
1028  p->path=DestroyString(p->path);
1029  }
1031  return((void *) NULL);
1032 }
1033 
1035 {
1036  if (policy_semaphore == (SemaphoreInfo *) NULL)
1039  if (policy_cache != (LinkedListInfo *) NULL)
1043 }
1044 
1045 /*
1046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1047 % %
1048 % %
1049 % %
1050 % S e t M a g i c k S e c u r i t y P o l i c y %
1051 % %
1052 % %
1053 % %
1054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1055 %
1056 % SetMagickSecurityPolicy() sets the ImageMagick security policy. It returns
1057 % MagickFalse if the policy is already set or if the policy does not parse.
1058 %
1059 % The format of the SetMagickSecurityPolicy method is:
1060 %
1061 % MagickBooleanType SetMagickSecurityPolicy(const char *policy,
1062 % ExceptionInfo *exception)
1063 %
1064 % A description of each parameter follows:
1065 %
1066 % o policy: the security policy in the XML format.
1067 %
1068 % o exception: return any errors or warnings in this structure.
1069 %
1070 */
1072  ExceptionInfo *exception)
1073 {
1074  PolicyInfo
1075  *p;
1076 
1078  status;
1079 
1080  assert(exception != (ExceptionInfo *) NULL);
1081  if (policy == (const char *) NULL)
1082  return(MagickFalse);
1083  if (IsPolicyCacheInstantiated(exception) == MagickFalse)
1084  return(MagickFalse);
1088  if ((p != (PolicyInfo *) NULL) && (p->domain != UndefinedPolicyDomain))
1089  {
1091  return(MagickFalse);
1092  }
1094  status=LoadPolicyCache(policy_cache,policy,"[user-policy]",0,exception);
1095  if (status == MagickFalse)
1096  return(MagickFalse);
1097  return(ResourceComponentGenesis());
1098 }
1099 
1100 /*
1101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1102 % %
1103 % %
1104 % %
1105 % 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 %
1106 % %
1107 % %
1108 % %
1109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1110 %
1111 % SetMagickSecurityPolicyValue() sets a value associated with an ImageMagick
1112 % security policy. For most policies, the value must be less than any value
1113 % set by the security policy configuration file (i.e. policy.xml). It returns
1114 % MagickFalse if the policy cannot be modified or if the policy does not parse.
1115 %
1116 % The format of the SetMagickSecurityPolicyValue method is:
1117 %
1118 % MagickBooleanType SetMagickSecurityPolicyValue(
1119 % const PolicyDomain domain,const char *name,const char *value,
1120 % ExceptionInfo *exception)
1121 %
1122 % A description of each parameter follows:
1123 %
1124 % o domain: the domain of the policy (e.g. system, resource).
1125 %
1126 % o name: the name of the policy.
1127 %
1128 % o value: the value to set the policy to.
1129 %
1130 % o exception: return any errors or warnings in this structure.
1131 %
1132 */
1133 
1135  const char *name,const char *value)
1136 {
1138  status;
1139 
1140  register PolicyInfo
1141  *p;
1142 
1143  status=MagickTrue;
1147  while (p != (PolicyInfo *) NULL)
1148  {
1149  if ((p->domain == domain) && (LocaleCompare(name,p->name) == 0))
1150  break;
1152  }
1153  if (p != (PolicyInfo *) NULL)
1154  {
1155  if (p->value != (char *) NULL)
1156  p->value=DestroyString(p->value);
1157  }
1158  else
1159  {
1160  p=(PolicyInfo *) AcquireCriticalMemory(sizeof(*p));
1161  (void) memset(p,0,sizeof(*p));
1162  p->exempt=MagickFalse;
1164  p->domain=domain;
1165  p->name=ConstantString(name);
1167  }
1168  p->value=ConstantString(value);
1170  if (status == MagickFalse)
1172  return(status);
1173 }
1174 
1176  const PolicyDomain domain,const char *name,const char *value,
1177  ExceptionInfo *exception)
1178 {
1179  char
1180  *current_value;
1181 
1182  magick_unreferenced(exception);
1183  assert(exception != (ExceptionInfo *) NULL);
1184  if ((name == (const char *) NULL) || (value == (const char *) NULL))
1185  return(MagickFalse);
1186  switch(domain)
1187  {
1188  case CachePolicyDomain:
1189  {
1190  if (LocaleCompare(name,"memory-map") == 0)
1191  {
1192  if (LocaleCompare(value,"anonymous") != 0)
1193  return(MagickFalse);
1196  return(SetPolicyValue(domain,name,value));
1197  }
1198  if (LocaleCompare(name,"synchronize") == 0)
1199  return(SetPolicyValue(domain,name,value));
1200  break;
1201  }
1202  case ResourcePolicyDomain:
1203  {
1204  ssize_t
1205  type;
1206 
1207  if (LocaleCompare(name,"temporary-path") == 0)
1208  return(SetPolicyValue(domain,name,value));
1210  if (type >= 0)
1211  {
1213  limit;
1214 
1215  limit=MagickResourceInfinity;
1216  if (LocaleCompare("unlimited",value) != 0)
1217  limit=StringToMagickSizeType(value,100.0);
1218  return(SetMagickResourceLimit((ResourceType) type,limit));
1219  }
1220  break;
1221  }
1222  case SystemPolicyDomain:
1223  {
1224  if (LocaleCompare(name,"max-memory-request") == 0)
1225  {
1226  current_value=GetPolicyValue("system:max-memory-request");
1227  if ((current_value == (char *) NULL) ||
1228  (StringToSizeType(value,100.0) < StringToSizeType(current_value,100.0)))
1229  {
1231  return(SetPolicyValue(domain,name,value));
1232  }
1233  }
1234  if (LocaleCompare(name,"memory-map") == 0)
1235  {
1236  if (LocaleCompare(value,"anonymous") != 0)
1237  return(MagickFalse);
1239  return(SetPolicyValue(domain,name,value));
1240  }
1241  if (LocaleCompare(name,"precision") == 0)
1242  {
1244  return(SetPolicyValue(domain,name,value));
1245  }
1246  if (LocaleCompare(name,"shred") == 0)
1247  {
1248  current_value=GetPolicyValue("system:shred");
1249  if ((current_value == (char *) NULL) ||
1250  (StringToInteger(value) > StringToInteger(current_value)))
1251  return(SetPolicyValue(domain,name,value));
1252  }
1253  break;
1254  }
1255  case CoderPolicyDomain:
1256  case DelegatePolicyDomain:
1257  case FilterPolicyDomain:
1258  case ModulePolicyDomain:
1259  case PathPolicyDomain:
1260  default:
1261  break;
1262  }
1263  return(MagickFalse);
1264 }
MagickBooleanType stealth
Definition: policy.c:95
char * value
Definition: policy.c:90
MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
Definition: resource.c:1154
#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:987
MagickExport MagickBooleanType ListPolicyInfo(FILE *file, ExceptionInfo *exception)
Definition: policy.c:668
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:2967
static SemaphoreInfo * policy_semaphore
Definition: policy.c:134
MagickPrivate void PolicyComponentTerminus(void)
Definition: policy.c:1034
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:1360
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:1175
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:767
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:1675
MagickExport const char * CommandOptionToMnemonic(const CommandOption option, const ssize_t type)
Definition: option.c:2680
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:347
size_t MagickSizeType
Definition: magick-type.h:130
#define MagickPathExtent
MagickExport MagickBooleanType IsStringTrue(const char *value)
Definition: string.c:1425
static MagickBooleanType SetPolicyValue(const PolicyDomain domain, const char *name, const char *value)
Definition: policy.c:1134
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:1397
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
MagickExport void GetNextToken(const char *start, const char **end, const size_t extent, char *token)
Definition: token.c:172
#define PolicyFilename
Definition: policy.c:73
#define MagickResourceInfinity
Definition: resource_.h:41
MagickExport MagickBooleanType SetMagickSecurityPolicy(const char *policy, ExceptionInfo *exception)
Definition: policy.c:1071
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:1013
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