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-2016 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 % http://www.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"
44 #include "MagickCore/client.h"
45 #include "MagickCore/configure.h"
46 #include "MagickCore/configure-private.h"
47 #include "MagickCore/exception.h"
48 #include "MagickCore/exception-private.h"
49 #include "MagickCore/memory_.h"
50 #include "MagickCore/monitor.h"
51 #include "MagickCore/monitor-private.h"
52 #include "MagickCore/option.h"
53 #include "MagickCore/policy.h"
54 #include "MagickCore/policy-private.h"
55 #include "MagickCore/semaphore.h"
56 #include "MagickCore/string_.h"
57 #include "MagickCore/token.h"
58 #include "MagickCore/utility.h"
59 #include "MagickCore/utility-private.h"
60 #include "MagickCore/xml-tree.h"
61 #include "MagickCore/xml-tree-private.h"
62
63 /*
64 Define declarations.
65 */
66 #define PolicyFilename "policy.xml"
67
68 /*
69 Typedef declarations.
70 */
71 struct _PolicyInfo
72 {
73 char
74 *path;
75
76 PolicyDomain
77 domain;
78
79 PolicyRights
80 rights;
81
82 char
83 *name,
84 *pattern,
85 *value;
86
87 MagickBooleanType
88 exempt,
89 stealth,
90 debug;
91
92 SemaphoreInfo
93 *semaphore;
94
95 size_t
96 signature;
97 };
98
99 typedef struct _PolicyMapInfo
100 {
101 const PolicyDomain
102 domain;
103
104 const PolicyRights
105 rights;
106
107 const char
108 *name,
109 *pattern,
110 *value;
111 } PolicyMapInfo;
112
113 /*
114 Static declarations.
115 */
116 static const PolicyMapInfo
117 PolicyMap[] =
118 {
119 { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
120 (const char *) NULL, (const char *) NULL }
121 };
122
123 static LinkedListInfo
124 *policy_cache = (LinkedListInfo *) NULL;
125
126 static SemaphoreInfo
127 *policy_semaphore = (SemaphoreInfo *) NULL;
128
129 /*
130 Forward declarations.
131 */
132 static MagickBooleanType
133 IsPolicyCacheInstantiated(ExceptionInfo *),
134 LoadPolicyCache(LinkedListInfo *,const char *,const char *,const size_t,
135 ExceptionInfo *);
136
137 /*
138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139 % %
140 % %
141 % %
142 % A c q u i r e P o l i c y C a c h e %
143 % %
144 % %
145 % %
146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147 %
148 % AcquirePolicyCache() caches one or more policy configurations which provides
149 % a mapping between policy attributes and a policy name.
150 %
151 % The format of the AcquirePolicyCache method is:
152 %
153 % LinkedListInfo *AcquirePolicyCache(const char *filename,
154 % ExceptionInfo *exception)
155 %
156 % A description of each parameter follows:
157 %
158 % o filename: the font file name.
159 %
160 % o exception: return any errors or warnings in this structure.
161 %
162 */
AcquirePolicyCache(const char * filename,ExceptionInfo * exception)163 static LinkedListInfo *AcquirePolicyCache(const char *filename,
164 ExceptionInfo *exception)
165 {
166 LinkedListInfo
167 *cache;
168
169 MagickStatusType
170 status;
171
172 register ssize_t
173 i;
174
175 /*
176 Load external policy map.
177 */
178 cache=NewLinkedList(0);
179 if (cache == (LinkedListInfo *) NULL)
180 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
181 status=MagickTrue;
182 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
183 {
184 const StringInfo
185 *option;
186
187 LinkedListInfo
188 *options;
189
190 options=GetConfigureOptions(filename,exception);
191 option=(const StringInfo *) GetNextValueInLinkedList(options);
192 while (option != (const StringInfo *) NULL)
193 {
194 status&=LoadPolicyCache(cache,(const char *)
195 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
196 option=(const StringInfo *) GetNextValueInLinkedList(options);
197 }
198 options=DestroyConfigureOptions(options);
199 }
200 #endif
201 /*
202 Load built-in policy map.
203 */
204 for (i=0; i < (ssize_t) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
205 {
206 PolicyInfo
207 *policy_info;
208
209 register const PolicyMapInfo
210 *p;
211
212 p=PolicyMap+i;
213 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
214 if (policy_info == (PolicyInfo *) NULL)
215 {
216 (void) ThrowMagickException(exception,GetMagickModule(),
217 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
218 continue;
219 }
220 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
221 policy_info->path=(char *) "[built-in]";
222 policy_info->domain=p->domain;
223 policy_info->rights=p->rights;
224 policy_info->name=(char *) p->name;
225 policy_info->pattern=(char *) p->pattern;
226 policy_info->value=(char *) p->value;
227 policy_info->exempt=MagickTrue;
228 policy_info->signature=MagickCoreSignature;
229 status&=AppendValueToLinkedList(cache,policy_info);
230 if (status == MagickFalse)
231 (void) ThrowMagickException(exception,GetMagickModule(),
232 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
233 }
234 return(cache);
235 }
236
237 /*
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 % %
240 % %
241 % %
242 + G e t P o l i c y I n f o %
243 % %
244 % %
245 % %
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 %
248 % GetPolicyInfo() searches the policy list for the specified name and if found
249 % returns attributes for that policy.
250 %
251 % The format of the GetPolicyInfo method is:
252 %
253 % PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
254 %
255 % A description of each parameter follows:
256 %
257 % o name: the policy name.
258 %
259 % o exception: return any errors or warnings in this structure.
260 %
261 */
GetPolicyInfo(const char * name,ExceptionInfo * exception)262 static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
263 {
264 char
265 policyname[MagickPathExtent];
266
267 register PolicyInfo
268 *p;
269
270 register char
271 *q;
272
273 assert(exception != (ExceptionInfo *) NULL);
274 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
275 return((PolicyInfo *) NULL);
276 /*
277 Strip names of whitespace.
278 */
279 *policyname='\0';
280 if (name != (const char *) NULL)
281 (void) CopyMagickString(policyname,name,MagickPathExtent);
282 for (q=policyname; *q != '\0'; q++)
283 {
284 if (isspace((int) ((unsigned char) *q)) == 0)
285 continue;
286 (void) CopyMagickString(q,q+1,MagickPathExtent);
287 q--;
288 }
289 /*
290 Search for policy tag.
291 */
292 LockSemaphoreInfo(policy_semaphore);
293 ResetLinkedListIterator(policy_cache);
294 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
295 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
296 {
297 UnlockSemaphoreInfo(policy_semaphore);
298 return(p);
299 }
300 while (p != (PolicyInfo *) NULL)
301 {
302 if (LocaleCompare(policyname,p->name) == 0)
303 break;
304 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
305 }
306 if (p != (PolicyInfo *) NULL)
307 (void) InsertValueInLinkedList(policy_cache,0,
308 RemoveElementByValueFromLinkedList(policy_cache,p));
309 UnlockSemaphoreInfo(policy_semaphore);
310 return(p);
311 }
312
313 /*
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 % %
316 % %
317 % %
318 % G e t P o l i c y I n f o L i s t %
319 % %
320 % %
321 % %
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 %
324 % GetPolicyInfoList() returns any policies that match the specified pattern.
325 %
326 % The format of the GetPolicyInfoList function is:
327 %
328 % const PolicyInfo **GetPolicyInfoList(const char *pattern,
329 % size_t *number_policies,ExceptionInfo *exception)
330 %
331 % A description of each parameter follows:
332 %
333 % o pattern: Specifies a pointer to a text string containing a pattern.
334 %
335 % o number_policies: returns the number of policies in the list.
336 %
337 % o exception: return any errors or warnings in this structure.
338 %
339 */
GetPolicyInfoList(const char * pattern,size_t * number_policies,ExceptionInfo * exception)340 MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
341 size_t *number_policies,ExceptionInfo *exception)
342 {
343 const PolicyInfo
344 **policies;
345
346 register const PolicyInfo
347 *p;
348
349 register ssize_t
350 i;
351
352 /*
353 Allocate policy list.
354 */
355 assert(pattern != (char *) NULL);
356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
357 assert(number_policies != (size_t *) NULL);
358 *number_policies=0;
359 p=GetPolicyInfo("*",exception);
360 if (p == (const PolicyInfo *) NULL)
361 return((const PolicyInfo **) NULL);
362 policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
363 GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
364 if (policies == (const PolicyInfo **) NULL)
365 return((const PolicyInfo **) NULL);
366 /*
367 Generate policy list.
368 */
369 LockSemaphoreInfo(policy_semaphore);
370 ResetLinkedListIterator(policy_cache);
371 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
372 for (i=0; p != (const PolicyInfo *) NULL; )
373 {
374 if ((p->stealth == MagickFalse) &&
375 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
376 policies[i++]=p;
377 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
378 }
379 UnlockSemaphoreInfo(policy_semaphore);
380 policies[i]=(PolicyInfo *) NULL;
381 *number_policies=(size_t) i;
382 return(policies);
383 }
384
385 /*
386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 % %
388 % %
389 % %
390 % G e t P o l i c y L i s t %
391 % %
392 % %
393 % %
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 %
396 % GetPolicyList() returns any policies that match the specified pattern.
397 %
398 % The format of the GetPolicyList function is:
399 %
400 % char **GetPolicyList(const char *pattern,size_t *number_policies,
401 % ExceptionInfo *exception)
402 %
403 % A description of each parameter follows:
404 %
405 % o pattern: a pointer to a text string containing a pattern.
406 %
407 % o number_policies: returns the number of policies in the list.
408 %
409 % o exception: return any errors or warnings in this structure.
410 %
411 */
GetPolicyList(const char * pattern,size_t * number_policies,ExceptionInfo * exception)412 MagickExport char **GetPolicyList(const char *pattern,
413 size_t *number_policies,ExceptionInfo *exception)
414 {
415 char
416 **policies;
417
418 register const PolicyInfo
419 *p;
420
421 register ssize_t
422 i;
423
424 /*
425 Allocate policy list.
426 */
427 assert(pattern != (char *) NULL);
428 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
429 assert(number_policies != (size_t *) NULL);
430 *number_policies=0;
431 p=GetPolicyInfo("*",exception);
432 if (p == (const PolicyInfo *) NULL)
433 return((char **) NULL);
434 policies=(char **) AcquireQuantumMemory((size_t)
435 GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
436 if (policies == (char **) NULL)
437 return((char **) NULL);
438 /*
439 Generate policy list.
440 */
441 LockSemaphoreInfo(policy_semaphore);
442 ResetLinkedListIterator(policy_cache);
443 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
444 for (i=0; p != (const PolicyInfo *) NULL; )
445 {
446 if ((p->stealth == MagickFalse) &&
447 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
448 policies[i++]=ConstantString(p->name);
449 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
450 }
451 UnlockSemaphoreInfo(policy_semaphore);
452 policies[i]=(char *) NULL;
453 *number_policies=(size_t) i;
454 return(policies);
455 }
456
457 /*
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 % %
460 % %
461 % %
462 % G e t P o l i c y V a l u e %
463 % %
464 % %
465 % %
466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467 %
468 % GetPolicyValue() returns the value associated with the named policy.
469 %
470 % The format of the GetPolicyValue method is:
471 %
472 % char *GetPolicyValue(const char *name)
473 %
474 % A description of each parameter follows:
475 %
476 % o policy_info: The policy info.
477 %
478 */
GetPolicyValue(const char * name)479 MagickExport char *GetPolicyValue(const char *name)
480 {
481 const char
482 *value;
483
484 const PolicyInfo
485 *policy_info;
486
487 ExceptionInfo
488 *exception;
489
490 assert(name != (const char *) NULL);
491 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
492 exception=AcquireExceptionInfo();
493 policy_info=GetPolicyInfo(name,exception);
494 exception=DestroyExceptionInfo(exception);
495 if (policy_info == (PolicyInfo *) NULL)
496 return((char *) NULL);
497 value=policy_info->value;
498 if ((value == (const char *) NULL) || (*value == '\0'))
499 return((char *) NULL);
500 return(ConstantString(value));
501 }
502
503 /*
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 % %
506 % %
507 % %
508 + 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 %
509 % %
510 % %
511 % %
512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 %
514 % IsPolicyCacheInstantiated() determines if the policy list is instantiated.
515 % If not, it instantiates the list and returns it.
516 %
517 % The format of the IsPolicyInstantiated method is:
518 %
519 % MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
520 %
521 % A description of each parameter follows.
522 %
523 % o exception: return any errors or warnings in this structure.
524 %
525 */
IsPolicyCacheInstantiated(ExceptionInfo * exception)526 static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
527 {
528 if (policy_cache == (LinkedListInfo *) NULL)
529 {
530 if (policy_semaphore == (SemaphoreInfo *) NULL)
531 ActivateSemaphoreInfo(&policy_semaphore);
532 LockSemaphoreInfo(policy_semaphore);
533 if (policy_cache == (LinkedListInfo *) NULL)
534 policy_cache=AcquirePolicyCache(PolicyFilename,exception);
535 UnlockSemaphoreInfo(policy_semaphore);
536 }
537 return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
538 }
539
540 /*
541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
542 % %
543 % %
544 % %
545 % I s R i g h t s A u t h o r i z e d %
546 % %
547 % %
548 % %
549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 %
551 % IsRightsAuthorized() returns MagickTrue if the policy authorizes the
552 % requested rights for the specified domain.
553 %
554 % The format of the IsRightsAuthorized method is:
555 %
556 % MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
557 % const PolicyRights rights,const char *pattern)
558 %
559 % A description of each parameter follows:
560 %
561 % o domain: the policy domain.
562 %
563 % o rights: the policy rights.
564 %
565 % o pattern: the coder, delegate, filter, or path pattern.
566 %
567 */
IsRightsAuthorized(const PolicyDomain domain,const PolicyRights rights,const char * pattern)568 MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
569 const PolicyRights rights,const char *pattern)
570 {
571 const PolicyInfo
572 *policy_info;
573
574 ExceptionInfo
575 *exception;
576
577 MagickBooleanType
578 authorized;
579
580 register PolicyInfo
581 *p;
582
583 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
584 "Domain: %s; rights=%s; pattern=\"%s\" ...",
585 CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
586 CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
587 exception=AcquireExceptionInfo();
588 policy_info=GetPolicyInfo("*",exception);
589 exception=DestroyExceptionInfo(exception);
590 if (policy_info == (PolicyInfo *) NULL)
591 return(MagickTrue);
592 authorized=MagickTrue;
593 LockSemaphoreInfo(policy_semaphore);
594 ResetLinkedListIterator(policy_cache);
595 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
596 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
597 {
598 if ((p->domain == domain) &&
599 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
600 {
601 if (((rights & ReadPolicyRights) != 0) &&
602 ((p->rights & ReadPolicyRights) == 0))
603 authorized=MagickFalse;
604 if (((rights & WritePolicyRights) != 0) &&
605 ((p->rights & WritePolicyRights) == 0))
606 authorized=MagickFalse;
607 if (((rights & ExecutePolicyRights) != 0) &&
608 ((p->rights & ExecutePolicyRights) == 0))
609 authorized=MagickFalse;
610 }
611 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
612 }
613 UnlockSemaphoreInfo(policy_semaphore);
614 return(authorized);
615 }
616
617 /*
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 % %
620 % %
621 % %
622 % L i s t P o l i c y I n f o %
623 % %
624 % %
625 % %
626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 %
628 % ListPolicyInfo() lists policies to the specified file.
629 %
630 % The format of the ListPolicyInfo method is:
631 %
632 % MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
633 %
634 % A description of each parameter follows.
635 %
636 % o file: List policy names to this file handle.
637 %
638 % o exception: return any errors or warnings in this structure.
639 %
640 */
ListPolicyInfo(FILE * file,ExceptionInfo * exception)641 MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
642 ExceptionInfo *exception)
643 {
644 const char
645 *path,
646 *domain;
647
648 const PolicyInfo
649 **policy_info;
650
651 register ssize_t
652 i;
653
654 size_t
655 number_policies;
656
657 /*
658 List name and attributes of each policy in the list.
659 */
660 if (file == (const FILE *) NULL)
661 file=stdout;
662 policy_info=GetPolicyInfoList("*",&number_policies,exception);
663 if (policy_info == (const PolicyInfo **) NULL)
664 return(MagickFalse);
665 path=(const char *) NULL;
666 for (i=0; i < (ssize_t) number_policies; i++)
667 {
668 if (policy_info[i]->stealth != MagickFalse)
669 continue;
670 if (((path == (const char *) NULL) ||
671 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
672 (policy_info[i]->path != (char *) NULL))
673 (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
674 path=policy_info[i]->path;
675 domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
676 policy_info[i]->domain);
677 (void) FormatLocaleFile(file," Policy: %s\n",domain);
678 if ((policy_info[i]->domain == CachePolicyDomain) ||
679 (policy_info[i]->domain == ResourcePolicyDomain) ||
680 (policy_info[i]->domain == SystemPolicyDomain))
681 {
682 if (policy_info[i]->name != (char *) NULL)
683 (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
684 if (policy_info[i]->value != (char *) NULL)
685 (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
686 }
687 else
688 {
689 (void) FormatLocaleFile(file," rights: ");
690 if (policy_info[i]->rights == NoPolicyRights)
691 (void) FormatLocaleFile(file,"None ");
692 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
693 (void) FormatLocaleFile(file,"Read ");
694 if ((policy_info[i]->rights & WritePolicyRights) != 0)
695 (void) FormatLocaleFile(file,"Write ");
696 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
697 (void) FormatLocaleFile(file,"Execute ");
698 (void) FormatLocaleFile(file,"\n");
699 if (policy_info[i]->pattern != (char *) NULL)
700 (void) FormatLocaleFile(file," pattern: %s\n",
701 policy_info[i]->pattern);
702 }
703 }
704 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
705 policy_info);
706 (void) fflush(file);
707 return(MagickTrue);
708 }
709
710 /*
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712 % %
713 % %
714 % %
715 + L o a d P o l i c y C a c h e %
716 % %
717 % %
718 % %
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720 %
721 % LoadPolicyCache() loads the policy configurations which provides a mapping
722 % between policy attributes and a policy domain.
723 %
724 % The format of the LoadPolicyCache method is:
725 %
726 % MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
727 % const char *filename,const size_t depth,ExceptionInfo *exception)
728 %
729 % A description of each parameter follows:
730 %
731 % o xml: The policy list in XML format.
732 %
733 % o filename: The policy list filename.
734 %
735 % o depth: depth of <include /> statements.
736 %
737 % o exception: return any errors or warnings in this structure.
738 %
739 */
LoadPolicyCache(LinkedListInfo * cache,const char * xml,const char * filename,const size_t depth,ExceptionInfo * exception)740 static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,const char *xml,
741 const char *filename,const size_t depth,ExceptionInfo *exception)
742 {
743 char
744 keyword[MagickPathExtent],
745 *token;
746
747 const char
748 *q;
749
750 MagickStatusType
751 status;
752
753 PolicyInfo
754 *policy_info;
755
756 size_t
757 extent;
758
759 /*
760 Load the policy map file.
761 */
762 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
763 "Loading policy file \"%s\" ...",filename);
764 if (xml == (char *) NULL)
765 return(MagickFalse);
766 status=MagickTrue;
767 policy_info=(PolicyInfo *) NULL;
768 token=AcquireString(xml);
769 extent=strlen(token)+MagickPathExtent;
770 for (q=(const char *) xml; *q != '\0'; )
771 {
772 /*
773 Interpret XML.
774 */
775 GetNextToken(q,&q,extent,token);
776 if (*token == '\0')
777 break;
778 (void) CopyMagickString(keyword,token,MagickPathExtent);
779 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
780 {
781 /*
782 Docdomain element.
783 */
784 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
785 GetNextToken(q,&q,extent,token);
786 continue;
787 }
788 if (LocaleNCompare(keyword,"<!--",4) == 0)
789 {
790 /*
791 Comment element.
792 */
793 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
794 GetNextToken(q,&q,extent,token);
795 continue;
796 }
797 if (LocaleCompare(keyword,"<include") == 0)
798 {
799 /*
800 Include element.
801 */
802 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
803 {
804 (void) CopyMagickString(keyword,token,MagickPathExtent);
805 GetNextToken(q,&q,extent,token);
806 if (*token != '=')
807 continue;
808 GetNextToken(q,&q,extent,token);
809 if (LocaleCompare(keyword,"file") == 0)
810 {
811 if (depth > 200)
812 (void) ThrowMagickException(exception,GetMagickModule(),
813 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
814 else
815 {
816 char
817 path[MagickPathExtent],
818 *file_xml;
819
820 GetPathComponent(filename,HeadPath,path);
821 if (*path != '\0')
822 (void) ConcatenateMagickString(path,DirectorySeparator,
823 MagickPathExtent);
824 if (*token == *DirectorySeparator)
825 (void) CopyMagickString(path,token,MagickPathExtent);
826 else
827 (void) ConcatenateMagickString(path,token,MagickPathExtent);
828 file_xml=FileToXML(path,~0UL);
829 if (file_xml != (char *) NULL)
830 {
831 status&=LoadPolicyCache(cache,file_xml,path,
832 depth+1,exception);
833 file_xml=DestroyString(file_xml);
834 }
835 }
836 }
837 }
838 continue;
839 }
840 if (LocaleCompare(keyword,"<policy") == 0)
841 {
842 /*
843 Policy element.
844 */
845 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
846 if (policy_info == (PolicyInfo *) NULL)
847 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
848 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
849 policy_info->path=ConstantString(filename);
850 policy_info->exempt=MagickFalse;
851 policy_info->signature=MagickCoreSignature;
852 continue;
853 }
854 if (policy_info == (PolicyInfo *) NULL)
855 continue;
856 if (LocaleCompare(keyword,"/>") == 0)
857 {
858 status=AppendValueToLinkedList(cache,policy_info);
859 if (status == MagickFalse)
860 (void) ThrowMagickException(exception,GetMagickModule(),
861 ResourceLimitError,"MemoryAllocationFailed","`%s'",
862 policy_info->name);
863 policy_info=(PolicyInfo *) NULL;
864 continue;
865 }
866 GetNextToken(q,(const char **) NULL,extent,token);
867 if (*token != '=')
868 continue;
869 GetNextToken(q,&q,extent,token);
870 GetNextToken(q,&q,extent,token);
871 switch (*keyword)
872 {
873 case 'D':
874 case 'd':
875 {
876 if (LocaleCompare((char *) keyword,"domain") == 0)
877 {
878 policy_info->domain=(PolicyDomain) ParseCommandOption(
879 MagickPolicyDomainOptions,MagickTrue,token);
880 break;
881 }
882 break;
883 }
884 case 'N':
885 case 'n':
886 {
887 if (LocaleCompare((char *) keyword,"name") == 0)
888 {
889 policy_info->name=ConstantString(token);
890 break;
891 }
892 break;
893 }
894 case 'P':
895 case 'p':
896 {
897 if (LocaleCompare((char *) keyword,"pattern") == 0)
898 {
899 policy_info->pattern=ConstantString(token);
900 break;
901 }
902 break;
903 }
904 case 'R':
905 case 'r':
906 {
907 if (LocaleCompare((char *) keyword,"rights") == 0)
908 {
909 policy_info->rights=(PolicyRights) ParseCommandOption(
910 MagickPolicyRightsOptions,MagickTrue,token);
911 break;
912 }
913 break;
914 }
915 case 'S':
916 case 's':
917 {
918 if (LocaleCompare((char *) keyword,"stealth") == 0)
919 {
920 policy_info->stealth=IsStringTrue(token);
921 break;
922 }
923 break;
924 }
925 case 'V':
926 case 'v':
927 {
928 if (LocaleCompare((char *) keyword,"value") == 0)
929 {
930 policy_info->value=ConstantString(token);
931 break;
932 }
933 break;
934 }
935 default:
936 break;
937 }
938 }
939 token=(char *) RelinquishMagickMemory(token);
940 return(status != 0 ? MagickTrue : MagickFalse);
941 }
942
943 /*
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 % %
946 % %
947 % %
948 + P o l i c y C o m p o n e n t G e n e s i s %
949 % %
950 % %
951 % %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %
954 % PolicyComponentGenesis() instantiates the policy component.
955 %
956 % The format of the PolicyComponentGenesis method is:
957 %
958 % MagickBooleanType PolicyComponentGenesis(void)
959 %
960 */
PolicyComponentGenesis(void)961 MagickPrivate MagickBooleanType PolicyComponentGenesis(void)
962 {
963 if (policy_semaphore == (SemaphoreInfo *) NULL)
964 policy_semaphore=AcquireSemaphoreInfo();
965 return(MagickTrue);
966 }
967
968 /*
969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970 % %
971 % %
972 % %
973 + P o l i c y C o m p o n e n t T e r m i n u s %
974 % %
975 % %
976 % %
977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 %
979 % PolicyComponentTerminus() destroys the policy component.
980 %
981 % The format of the PolicyComponentTerminus method is:
982 %
983 % PolicyComponentTerminus(void)
984 %
985 */
986
DestroyPolicyElement(void * policy_info)987 static void *DestroyPolicyElement(void *policy_info)
988 {
989 register PolicyInfo
990 *p;
991
992 p=(PolicyInfo *) policy_info;
993 if (p->exempt == MagickFalse)
994 {
995 if (p->value != (char *) NULL)
996 p->value=DestroyString(p->value);
997 if (p->pattern != (char *) NULL)
998 p->pattern=DestroyString(p->pattern);
999 if (p->name != (char *) NULL)
1000 p->name=DestroyString(p->name);
1001 if (p->path != (char *) NULL)
1002 p->path=DestroyString(p->path);
1003 }
1004 p=(PolicyInfo *) RelinquishMagickMemory(p);
1005 return((void *) NULL);
1006 }
1007
PolicyComponentTerminus(void)1008 MagickPrivate void PolicyComponentTerminus(void)
1009 {
1010 if (policy_semaphore == (SemaphoreInfo *) NULL)
1011 ActivateSemaphoreInfo(&policy_semaphore);
1012 LockSemaphoreInfo(policy_semaphore);
1013 if (policy_cache != (LinkedListInfo *) NULL)
1014 policy_cache=DestroyLinkedList(policy_cache,DestroyPolicyElement);
1015 UnlockSemaphoreInfo(policy_semaphore);
1016 RelinquishSemaphoreInfo(&policy_semaphore);
1017 }
1018