blob: 747ce5214c76999f8e9d80bdb6f002191d78e134 [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% %
cristy7e41fe82010-12-04 23:12:08 +000019% Copyright 1999-2011 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*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
44#include "MagickCore/client.h"
45#include "MagickCore/configure.h"
46#include "MagickCore/exception.h"
47#include "MagickCore/exception-private.h"
48#include "MagickCore/memory_.h"
49#include "MagickCore/monitor.h"
50#include "MagickCore/monitor-private.h"
51#include "MagickCore/option.h"
52#include "MagickCore/policy.h"
cristy5ff4eaf2011-09-03 01:38:02 +000053#include "MagickCore/policy-private.h"
cristy4c08aed2011-07-01 19:47:50 +000054#include "MagickCore/semaphore.h"
55#include "MagickCore/string_.h"
56#include "MagickCore/token.h"
57#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000058#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000059#include "MagickCore/xml-tree.h"
cristy3ed852e2009-09-05 21:47:34 +000060
61/*
62 Define declarations.
63*/
64#define PolicyFilename "policy.xml"
65
66/*
cristy54a531d2009-10-21 17:58:01 +000067 Typedef declarations.
cristy3ed852e2009-09-05 21:47:34 +000068*/
69struct _PolicyInfo
70{
71 char
cristy54a531d2009-10-21 17:58:01 +000072 *path;
cristy3ed852e2009-09-05 21:47:34 +000073
74 PolicyDomain
75 domain;
76
77 PolicyRights
78 rights;
79
80 char
cristy54a531d2009-10-21 17:58:01 +000081 *name,
cristy3ed852e2009-09-05 21:47:34 +000082 *pattern,
83 *value;
84
85 MagickBooleanType
cristy54a531d2009-10-21 17:58:01 +000086 exempt,
cristy3ed852e2009-09-05 21:47:34 +000087 stealth,
88 debug;
89
90 SemaphoreInfo
91 *semaphore;
92
cristybb503372010-05-27 20:51:26 +000093 size_t
cristy3ed852e2009-09-05 21:47:34 +000094 signature;
95};
cristy54a531d2009-10-21 17:58:01 +000096
97typedef struct _PolicyMapInfo
98{
99 const PolicyDomain
100 domain;
101
102 const PolicyRights
103 rights;
104
105 const char
106 *name,
107 *pattern,
108 *value;
109} PolicyMapInfo;
cristy3ed852e2009-09-05 21:47:34 +0000110
111/*
112 Static declarations.
113*/
cristy54a531d2009-10-21 17:58:01 +0000114static const PolicyMapInfo
115 PolicyMap[] =
116 {
cristyfa378d92009-10-23 15:41:15 +0000117 { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
118 (const char *) NULL, (const char *) NULL }
cristy54a531d2009-10-21 17:58:01 +0000119 };
120
cristy3ed852e2009-09-05 21:47:34 +0000121static LinkedListInfo
122 *policy_list = (LinkedListInfo *) NULL;
123
124static SemaphoreInfo
125 *policy_semaphore = (SemaphoreInfo *) NULL;
126
127static volatile MagickBooleanType
128 instantiate_policy = MagickFalse;
129
130/*
131 Forward declarations.
132*/
133static MagickBooleanType
134 InitializePolicyList(ExceptionInfo *),
135 LoadPolicyLists(const char *,ExceptionInfo *);
136
137/*
138%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139% %
140% %
141% %
cristy3ed852e2009-09-05 21:47:34 +0000142+ G e t P o l i c y I n f o %
143% %
144% %
145% %
146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147%
148% GetPolicyInfo() searches the policy list for the specified name and if found
149% returns attributes for that policy.
150%
151% The format of the GetPolicyInfo method is:
152%
153% PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
154%
155% A description of each parameter follows:
156%
157% o name: the policy name.
158%
159% o exception: return any errors or warnings in this structure.
160%
161*/
162static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
163{
164 char
165 policyname[MaxTextExtent];
166
167 register PolicyInfo
168 *p;
169
170 register char
171 *q;
172
173 assert(exception != (ExceptionInfo *) NULL);
174 if ((policy_list == (LinkedListInfo *) NULL) ||
175 (instantiate_policy == MagickFalse))
176 if (InitializePolicyList(exception) == MagickFalse)
177 return((PolicyInfo *) NULL);
178 if ((policy_list == (LinkedListInfo *) NULL) ||
179 (IsLinkedListEmpty(policy_list) != MagickFalse))
180 return((PolicyInfo *) NULL);
181 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
182 return((PolicyInfo *) GetValueFromLinkedList(policy_list,0));
183 /*
184 Strip names of whitespace.
185 */
186 (void) CopyMagickString(policyname,name,MaxTextExtent);
187 for (q=policyname; *q != '\0'; q++)
188 {
189 if (isspace((int) ((unsigned char) *q)) == 0)
190 continue;
191 (void) CopyMagickString(q,q+1,MaxTextExtent);
192 q--;
193 }
194 /*
195 Search for policy tag.
196 */
cristyf84a1932010-01-03 18:00:18 +0000197 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000198 ResetLinkedListIterator(policy_list);
199 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
200 while (p != (PolicyInfo *) NULL)
201 {
202 if (LocaleCompare(policyname,p->name) == 0)
203 break;
204 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
205 }
cristy6446d622009-11-02 01:17:45 +0000206 if (p != (PolicyInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000207 (void) InsertValueInLinkedList(policy_list,0,
208 RemoveElementByValueFromLinkedList(policy_list,p));
cristyf84a1932010-01-03 18:00:18 +0000209 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000210 return(p);
211}
212
213/*
214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215% %
216% %
217% %
218% G e t P o l i c y I n f o L i s t %
219% %
220% %
221% %
222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223%
224% GetPolicyInfoList() returns any policies that match the specified pattern.
225%
226% The format of the GetPolicyInfoList function is:
227%
228% const PolicyInfo **GetPolicyInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000229% size_t *number_policies,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000230%
231% A description of each parameter follows:
232%
233% o pattern: Specifies a pointer to a text string containing a pattern.
234%
235% o number_policies: returns the number of policies in the list.
236%
237% o exception: return any errors or warnings in this structure.
238%
239*/
240MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000241 size_t *number_policies,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000242{
243 const PolicyInfo
244 **policies;
245
246 register const PolicyInfo
247 *p;
248
cristybb503372010-05-27 20:51:26 +0000249 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000250 i;
251
252 /*
253 Allocate policy list.
254 */
255 assert(pattern != (char *) NULL);
256 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000257 assert(number_policies != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000258 *number_policies=0;
259 p=GetPolicyInfo("*",exception);
260 if (p == (const PolicyInfo *) NULL)
261 return((const PolicyInfo **) NULL);
262 policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
263 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
264 if (policies == (const PolicyInfo **) NULL)
265 return((const PolicyInfo **) NULL);
266 /*
267 Generate policy list.
268 */
cristyf84a1932010-01-03 18:00:18 +0000269 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000270 ResetLinkedListIterator(policy_list);
271 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
272 for (i=0; p != (const PolicyInfo *) NULL; )
273 {
274 if ((p->stealth == MagickFalse) &&
275 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
276 policies[i++]=p;
277 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
278 }
cristyf84a1932010-01-03 18:00:18 +0000279 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000280 policies[i]=(PolicyInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000281 *number_policies=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000282 return(policies);
283}
284
285/*
286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287% %
288% %
289% %
290% G e t P o l i c y L i s t %
291% %
292% %
293% %
294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295%
296% GetPolicyList() returns any policies that match the specified pattern.
297%
298% The format of the GetPolicyList function is:
299%
cristybb503372010-05-27 20:51:26 +0000300% char **GetPolicyList(const char *pattern,size_t *number_policies,
cristy3ed852e2009-09-05 21:47:34 +0000301% ExceptionInfo *exception)
302%
303% A description of each parameter follows:
304%
305% o pattern: a pointer to a text string containing a pattern.
306%
307% o number_policies: returns the number of policies in the list.
308%
309% o exception: return any errors or warnings in this structure.
310%
311*/
312MagickExport char **GetPolicyList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000313 size_t *number_policies,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000314{
315 char
316 **policies;
317
318 register const PolicyInfo
319 *p;
320
cristybb503372010-05-27 20:51:26 +0000321 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000322 i;
323
324 /*
325 Allocate policy list.
326 */
327 assert(pattern != (char *) NULL);
328 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000329 assert(number_policies != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000330 *number_policies=0;
331 p=GetPolicyInfo("*",exception);
332 if (p == (const PolicyInfo *) NULL)
333 return((char **) NULL);
334 policies=(char **) AcquireQuantumMemory((size_t)
335 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
336 if (policies == (char **) NULL)
337 return((char **) NULL);
338 /*
339 Generate policy list.
340 */
cristyf84a1932010-01-03 18:00:18 +0000341 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000342 ResetLinkedListIterator(policy_list);
343 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
344 for (i=0; p != (const PolicyInfo *) NULL; )
345 {
346 if ((p->stealth == MagickFalse) &&
347 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
348 policies[i++]=ConstantString(p->name);
349 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
350 }
cristyf84a1932010-01-03 18:00:18 +0000351 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000352 policies[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000353 *number_policies=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000354 return(policies);
355}
356
357/*
358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359% %
360% %
361% %
362% G e t P o l i c y V a l u e %
363% %
364% %
365% %
366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367%
368% GetPolicyValue() returns the value associated with the named policy.
369%
370% The format of the GetPolicyValue method is:
371%
372% char *GetPolicyValue(const char *name)
373%
374% A description of each parameter follows:
375%
376% o policy_info: The policy info.
377%
378*/
379MagickExport char *GetPolicyValue(const char *name)
380{
381 const char
382 *value;
383
384 const PolicyInfo
385 *policy_info;
386
387 ExceptionInfo
388 *exception;
389
390 assert(name != (const char *) NULL);
391 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
392 exception=AcquireExceptionInfo();
393 policy_info=GetPolicyInfo(name,exception);
394 exception=DestroyExceptionInfo(exception);
395 if (policy_info == (PolicyInfo *) NULL)
396 return((char *) NULL);
397 value=policy_info->value;
398 if ((value == (const char *) NULL) || (*value == '\0'))
399 return((char *) NULL);
400 return(ConstantString(value));
401}
402
403/*
404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405% %
406% %
407% %
408+ I n i t i a l i z e P o l i c y L i s t %
409% %
410% %
411% %
412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413%
414% InitializePolicyList() initializes the policy list.
415%
416% The format of the InitializePolicyList method is:
417%
418% MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
419%
420% A description of each parameter follows.
421%
422% o exception: return any errors or warnings in this structure.
423%
424*/
425static MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
426{
427 if ((policy_list == (LinkedListInfo *) NULL) &&
428 (instantiate_policy == MagickFalse))
429 {
cristy4e1dff62009-10-25 20:36:03 +0000430 if (policy_semaphore == (SemaphoreInfo *) NULL)
431 AcquireSemaphoreInfo(&policy_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000432 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000433 if ((policy_list == (LinkedListInfo *) NULL) &&
434 (instantiate_policy == MagickFalse))
435 {
436 (void) LoadPolicyLists(PolicyFilename,exception);
437 instantiate_policy=MagickTrue;
438 }
cristyf84a1932010-01-03 18:00:18 +0000439 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000440 }
441 return(policy_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
442}
443
444/*
445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446% %
447% %
448% %
cristy3ed852e2009-09-05 21:47:34 +0000449% I s R i g h t s A u t h o r i z e d %
450% %
451% %
452% %
453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454%
455% IsRightsAuthorized() returns MagickTrue if the policy authorizes the
456% requested rights for the specified domain.
457%
458% The format of the IsRightsAuthorized method is:
459%
460% MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
461% const PolicyRights rights,const char *pattern)
462%
463% A description of each parameter follows:
464%
465% o domain: the policy domain.
466%
467% o rights: the policy rights.
468%
469% o pattern: the coder, delegate, filter, or path pattern.
470%
471*/
472MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
473 const PolicyRights rights,const char *pattern)
474{
475 const PolicyInfo
476 *policy_info;
477
478 ExceptionInfo
479 *exception;
480
481 MagickBooleanType
482 authorized;
483
484 register PolicyInfo
485 *p;
486
487 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
488 "Domain: %s; rights=%s; pattern=\"%s\" ...",
cristy042ee782011-04-22 18:48:30 +0000489 CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
490 CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
cristy3ed852e2009-09-05 21:47:34 +0000491 exception=AcquireExceptionInfo();
492 policy_info=GetPolicyInfo("*",exception);
493 exception=DestroyExceptionInfo(exception);
494 if (policy_info == (PolicyInfo *) NULL)
495 return(MagickTrue);
496 authorized=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +0000497 LockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000498 ResetLinkedListIterator(policy_list);
499 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
500 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
501 {
502 if ((p->domain == domain) &&
503 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
504 {
505 if (((rights & ReadPolicyRights) != 0) &&
506 ((p->rights & ReadPolicyRights) == 0))
507 authorized=MagickFalse;
508 if (((rights & WritePolicyRights) != 0) &&
509 ((p->rights & WritePolicyRights) == 0))
510 authorized=MagickFalse;
511 if (((rights & ExecutePolicyRights) != 0) &&
512 ((p->rights & ExecutePolicyRights) == 0))
513 authorized=MagickFalse;
514 }
515 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
516 }
cristyf84a1932010-01-03 18:00:18 +0000517 UnlockSemaphoreInfo(policy_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000518 return(authorized);
519}
520
521/*
522%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
523% %
524% %
525% %
526% L i s t P o l i c y I n f o %
527% %
528% %
529% %
530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
531%
532% ListPolicyInfo() lists policies to the specified file.
533%
534% The format of the ListPolicyInfo method is:
535%
536% MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
537%
538% A description of each parameter follows.
539%
540% o file: List policy names to this file handle.
541%
542% o exception: return any errors or warnings in this structure.
543%
544*/
545MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
546 ExceptionInfo *exception)
547{
548 const char
549 *path,
550 *domain;
551
552 const PolicyInfo
553 **policy_info;
554
cristybb503372010-05-27 20:51:26 +0000555 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000556 i;
557
cristybb503372010-05-27 20:51:26 +0000558 size_t
cristy3ed852e2009-09-05 21:47:34 +0000559 number_policies;
560
561 /*
562 List name and attributes of each policy in the list.
563 */
564 if (file == (const FILE *) NULL)
565 file=stdout;
566 policy_info=GetPolicyInfoList("*",&number_policies,exception);
567 if (policy_info == (const PolicyInfo **) NULL)
568 return(MagickFalse);
569 path=(const char *) NULL;
cristybb503372010-05-27 20:51:26 +0000570 for (i=0; i < (ssize_t) number_policies; i++)
cristy3ed852e2009-09-05 21:47:34 +0000571 {
572 if (policy_info[i]->stealth != MagickFalse)
573 continue;
574 if (((path == (const char *) NULL) ||
575 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
576 (policy_info[i]->path != (char *) NULL))
cristyb51dff52011-05-19 16:55:47 +0000577 (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
cristy3ed852e2009-09-05 21:47:34 +0000578 path=policy_info[i]->path;
cristy042ee782011-04-22 18:48:30 +0000579 domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
cristy3ed852e2009-09-05 21:47:34 +0000580 policy_info[i]->domain);
cristyb51dff52011-05-19 16:55:47 +0000581 (void) FormatLocaleFile(file," Policy: %s\n",domain);
cristy7ce14bc2010-01-17 00:01:01 +0000582 if ((policy_info[i]->domain == ResourcePolicyDomain) ||
583 (policy_info[i]->domain == SystemPolicyDomain))
cristy3ed852e2009-09-05 21:47:34 +0000584 {
585 if (policy_info[i]->name != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000586 (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
cristy3ed852e2009-09-05 21:47:34 +0000587 if (policy_info[i]->value != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000588 (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
cristy3ed852e2009-09-05 21:47:34 +0000589 }
590 else
591 {
cristyb51dff52011-05-19 16:55:47 +0000592 (void) FormatLocaleFile(file," rights: ");
cristy3ed852e2009-09-05 21:47:34 +0000593 if (policy_info[i]->rights == NoPolicyRights)
cristyb51dff52011-05-19 16:55:47 +0000594 (void) FormatLocaleFile(file,"None ");
cristy3ed852e2009-09-05 21:47:34 +0000595 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
cristyb51dff52011-05-19 16:55:47 +0000596 (void) FormatLocaleFile(file,"Read ");
cristy3ed852e2009-09-05 21:47:34 +0000597 if ((policy_info[i]->rights & WritePolicyRights) != 0)
cristyb51dff52011-05-19 16:55:47 +0000598 (void) FormatLocaleFile(file,"Write ");
cristy3ed852e2009-09-05 21:47:34 +0000599 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
cristyb51dff52011-05-19 16:55:47 +0000600 (void) FormatLocaleFile(file,"Execute ");
601 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +0000602 if (policy_info[i]->pattern != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +0000603 (void) FormatLocaleFile(file," pattern: %s\n",
604 policy_info[i]->pattern);
cristy3ed852e2009-09-05 21:47:34 +0000605 }
606 }
607 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
608 policy_info);
609 (void) fflush(file);
610 return(MagickTrue);
611}
612
613/*
614%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
615% %
616% %
617% %
618+ L o a d P o l i c y L i s t %
619% %
620% %
621% %
622%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623%
624% LoadPolicyList() loads the policy configuration file which provides a mapping
625% between policy attributes and a policy domain.
626%
627% The format of the LoadPolicyList method is:
628%
629% MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000630% const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000631%
632% A description of each parameter follows:
633%
634% o xml: The policy list in XML format.
635%
636% o filename: The policy list filename.
637%
638% o depth: depth of <include /> statements.
639%
640% o exception: return any errors or warnings in this structure.
641%
642*/
643static MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000644 const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000645{
646 char
647 keyword[MaxTextExtent],
648 *token;
649
650 PolicyInfo
651 *policy_info;
652
653 const char
654 *q;
655
656 MagickBooleanType
657 status;
658
659 /*
660 Load the policy map file.
661 */
662 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
663 "Loading policy file \"%s\" ...",filename);
664 if (xml == (char *) NULL)
665 return(MagickFalse);
666 if (policy_list == (LinkedListInfo *) NULL)
667 {
668 policy_list=NewLinkedList(0);
669 if (policy_list == (LinkedListInfo *) NULL)
670 {
671 ThrowFileException(exception,ResourceLimitError,
672 "MemoryAllocationFailed",filename);
673 return(MagickFalse);
674 }
675 }
676 status=MagickTrue;
677 policy_info=(PolicyInfo *) NULL;
678 token=AcquireString(xml);
679 for (q=(const char *) xml; *q != '\0'; )
680 {
681 /*
682 Interpret XML.
683 */
684 GetMagickToken(q,&q,token);
685 if (*token == '\0')
686 break;
687 (void) CopyMagickString(keyword,token,MaxTextExtent);
688 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
689 {
690 /*
691 Docdomain element.
692 */
693 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
694 GetMagickToken(q,&q,token);
695 continue;
696 }
697 if (LocaleNCompare(keyword,"<!--",4) == 0)
698 {
699 /*
700 Comment element.
701 */
702 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
703 GetMagickToken(q,&q,token);
704 continue;
705 }
706 if (LocaleCompare(keyword,"<include") == 0)
707 {
708 /*
709 Include element.
710 */
711 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
712 {
713 (void) CopyMagickString(keyword,token,MaxTextExtent);
714 GetMagickToken(q,&q,token);
715 if (*token != '=')
716 continue;
717 GetMagickToken(q,&q,token);
718 if (LocaleCompare(keyword,"file") == 0)
719 {
720 if (depth > 200)
721 (void) ThrowMagickException(exception,GetMagickModule(),
722 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
723 else
724 {
725 char
726 path[MaxTextExtent],
727 *xml;
728
729 GetPathComponent(filename,HeadPath,path);
730 if (*path != '\0')
731 (void) ConcatenateMagickString(path,DirectorySeparator,
732 MaxTextExtent);
733 if (*token == *DirectorySeparator)
734 (void) CopyMagickString(path,token,MaxTextExtent);
735 else
736 (void) ConcatenateMagickString(path,token,MaxTextExtent);
737 xml=FileToString(path,~0,exception);
738 if (xml != (char *) NULL)
739 {
740 status=LoadPolicyList(xml,path,depth+1,exception);
741 xml=(char *) RelinquishMagickMemory(xml);
742 }
743 }
744 }
745 }
746 continue;
747 }
748 if (LocaleCompare(keyword,"<policy") == 0)
749 {
750 /*
751 Policy element.
752 */
cristy73bd4a52010-10-05 11:24:23 +0000753 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
cristy3ed852e2009-09-05 21:47:34 +0000754 if (policy_info == (PolicyInfo *) NULL)
755 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
756 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
757 policy_info->path=ConstantString(filename);
cristy54a531d2009-10-21 17:58:01 +0000758 policy_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000759 policy_info->signature=MagickSignature;
760 continue;
761 }
762 if (policy_info == (PolicyInfo *) NULL)
763 continue;
764 if (LocaleCompare(keyword,"/>") == 0)
765 {
766 status=AppendValueToLinkedList(policy_list,policy_info);
767 if (status == MagickFalse)
768 (void) ThrowMagickException(exception,GetMagickModule(),
769 ResourceLimitError,"MemoryAllocationFailed","`%s'",
770 policy_info->name);
771 policy_info=(PolicyInfo *) NULL;
772 }
773 GetMagickToken(q,(const char **) NULL,token);
774 if (*token != '=')
775 continue;
776 GetMagickToken(q,&q,token);
777 GetMagickToken(q,&q,token);
778 switch (*keyword)
779 {
780 case 'D':
781 case 'd':
782 {
783 if (LocaleCompare((char *) keyword,"domain") == 0)
784 {
cristy042ee782011-04-22 18:48:30 +0000785 policy_info->domain=(PolicyDomain) ParseCommandOption(
cristy3ed852e2009-09-05 21:47:34 +0000786 MagickPolicyDomainOptions,MagickTrue,token);
787 break;
788 }
789 break;
790 }
791 case 'N':
792 case 'n':
793 {
794 if (LocaleCompare((char *) keyword,"name") == 0)
795 {
796 policy_info->name=ConstantString(token);
797 break;
798 }
799 break;
800 }
801 case 'P':
802 case 'p':
803 {
804 if (LocaleCompare((char *) keyword,"pattern") == 0)
805 {
806 policy_info->pattern=ConstantString(token);
807 break;
808 }
809 break;
810 }
811 case 'R':
812 case 'r':
813 {
814 if (LocaleCompare((char *) keyword,"rights") == 0)
815 {
cristy042ee782011-04-22 18:48:30 +0000816 policy_info->rights=(PolicyRights) ParseCommandOption(
cristy3ed852e2009-09-05 21:47:34 +0000817 MagickPolicyRightsOptions,MagickTrue,token);
818 break;
819 }
820 break;
821 }
822 case 'S':
823 case 's':
824 {
825 if (LocaleCompare((char *) keyword,"stealth") == 0)
826 {
827 policy_info->stealth=IsMagickTrue(token);
828 break;
829 }
830 break;
831 }
832 case 'V':
833 case 'v':
834 {
835 if (LocaleCompare((char *) keyword,"value") == 0)
836 {
837 policy_info->value=ConstantString(token);
838 break;
839 }
840 break;
841 }
842 default:
843 break;
844 }
845 }
846 token=(char *) RelinquishMagickMemory(token);
847 return(status);
848}
849
850/*
851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852% %
853% %
854% %
855% L o a d P o l i c y L i s t s %
856% %
857% %
858% %
859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860%
861% LoadPolicyList() loads one or more policy configuration file which provides a
862% mapping between policy attributes and a policy name.
863%
864% The format of the LoadPolicyLists method is:
865%
866% MagickBooleanType LoadPolicyLists(const char *filename,
867% ExceptionInfo *exception)
868%
869% A description of each parameter follows:
870%
871% o filename: the font file name.
872%
873% o exception: return any errors or warnings in this structure.
874%
875*/
876static MagickBooleanType LoadPolicyLists(const char *filename,
877 ExceptionInfo *exception)
878{
cristy3ed852e2009-09-05 21:47:34 +0000879 const StringInfo
880 *option;
881
882 LinkedListInfo
883 *options;
884
885 MagickStatusType
886 status;
887
cristybb503372010-05-27 20:51:26 +0000888 register ssize_t
cristy54a531d2009-10-21 17:58:01 +0000889 i;
890
891 /*
892 Load built-in policy map.
893 */
cristy3ed852e2009-09-05 21:47:34 +0000894 status=MagickFalse;
cristy54a531d2009-10-21 17:58:01 +0000895 if (policy_list == (LinkedListInfo *) NULL)
896 {
897 policy_list=NewLinkedList(0);
898 if (policy_list == (LinkedListInfo *) NULL)
899 {
900 ThrowFileException(exception,ResourceLimitError,
901 "MemoryAllocationFailed",filename);
902 return(MagickFalse);
903 }
904 }
cristybb503372010-05-27 20:51:26 +0000905 for (i=0; i < (ssize_t) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
cristy54a531d2009-10-21 17:58:01 +0000906 {
907 PolicyInfo
908 *policy_info;
909
910 register const PolicyMapInfo
911 *p;
912
913 p=PolicyMap+i;
cristy73bd4a52010-10-05 11:24:23 +0000914 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
cristy54a531d2009-10-21 17:58:01 +0000915 if (policy_info == (PolicyInfo *) NULL)
916 {
917 (void) ThrowMagickException(exception,GetMagickModule(),
918 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
919 continue;
920 }
921 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
922 policy_info->path=(char *) "[built-in]";
923 policy_info->domain=p->domain;
924 policy_info->rights=p->rights;
925 policy_info->name=(char *) p->name;
926 policy_info->pattern=(char *) p->pattern;
927 policy_info->value=(char *) p->value;
928 policy_info->exempt=MagickTrue;
929 policy_info->signature=MagickSignature;
930 status=AppendValueToLinkedList(policy_list,policy_info);
931 if (status == MagickFalse)
932 (void) ThrowMagickException(exception,GetMagickModule(),
933 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
934 }
935 /*
936 Load external policy map.
937 */
cristy3ed852e2009-09-05 21:47:34 +0000938 options=GetConfigureOptions(filename,exception);
939 option=(const StringInfo *) GetNextValueInLinkedList(options);
940 while (option != (const StringInfo *) NULL)
941 {
942 status|=LoadPolicyList((const char *) GetStringInfoDatum(option),
943 GetStringInfoPath(option),0,exception);
944 option=(const StringInfo *) GetNextValueInLinkedList(options);
945 }
946 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +0000947 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000948}
cristyf34a1452009-10-24 22:29:27 +0000949
950/*
951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952% %
953% %
954% %
955+ P o l i c y C o m p o n e n t G e n e s i s %
956% %
957% %
958% %
959%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
960%
961% PolicyComponentGenesis() instantiates the policy component.
962%
963% The format of the PolicyComponentGenesis method is:
964%
965% MagickBooleanType PolicyComponentGenesis(void)
966%
967*/
cristy5ff4eaf2011-09-03 01:38:02 +0000968MagickPrivate MagickBooleanType PolicyComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000969{
cristy165b6092009-10-26 13:52:10 +0000970 AcquireSemaphoreInfo(&policy_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000971 return(MagickTrue);
972}
973
974/*
975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976% %
977% %
978% %
979+ P o l i c y C o m p o n e n t T e r m i n u s %
980% %
981% %
982% %
983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984%
985% PolicyComponentTerminus() destroys the policy component.
986%
987% The format of the PolicyComponentTerminus method is:
988%
989% PolicyComponentTerminus(void)
990%
991*/
992
993static void *DestroyPolicyElement(void *policy_info)
994{
995 register PolicyInfo
996 *p;
997
998 p=(PolicyInfo *) policy_info;
999 if (p->exempt == MagickFalse)
1000 {
1001 if (p->value != (char *) NULL)
1002 p->value=DestroyString(p->value);
1003 if (p->pattern != (char *) NULL)
1004 p->pattern=DestroyString(p->pattern);
1005 if (p->name != (char *) NULL)
1006 p->name=DestroyString(p->name);
1007 if (p->path != (char *) NULL)
1008 p->path=DestroyString(p->path);
1009 }
1010 p=(PolicyInfo *) RelinquishMagickMemory(p);
1011 return((void *) NULL);
1012}
1013
cristy5ff4eaf2011-09-03 01:38:02 +00001014MagickPrivate void PolicyComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001015{
cristy18b17442009-10-25 18:36:48 +00001016 if (policy_semaphore == (SemaphoreInfo *) NULL)
1017 AcquireSemaphoreInfo(&policy_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001018 LockSemaphoreInfo(policy_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001019 if (policy_list != (LinkedListInfo *) NULL)
1020 policy_list=DestroyLinkedList(policy_list,DestroyPolicyElement);
1021 instantiate_policy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001022 UnlockSemaphoreInfo(policy_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001023 DestroySemaphoreInfo(&policy_semaphore);
1024}