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*/ 71struct _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 99typedef 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*/ 116static const PolicyMapInfo 117 PolicyMap[] = 118 { 119 { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL, 120 (const char *) NULL, (const char *) NULL } 121 }; 122 123static LinkedListInfo 124 *policy_cache = (LinkedListInfo *) NULL; 125 126static SemaphoreInfo 127 *policy_semaphore = (SemaphoreInfo *) NULL; 128 129/* 130 Forward declarations. 131*/ 132static 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*/ 163static 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*/ 262static 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*/ 340MagickExport 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*/ 412MagickExport 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*/ 479MagickExport 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*/ 526static 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*/ 568MagickExport 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*/ 641MagickExport 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*/ 740static 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*/ 961MagickPrivate 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 987static 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 1008MagickPrivate 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