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