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