Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
6.1 KiB

  1. #include <wininetp.h>
  2. #include "policyref.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #pragma warning(disable:4800)
  6. /*
  7. Determine whether given string matches the pattern in second argument
  8. The only wildcard allowed is "*" which stands for zero or more characters
  9. (equivalent to the regular-expression construct "(.*)"
  10. The algorithm here breaks up the pattern into a series of asteriks-seperated
  11. literals and tries to locate each literal inside the search string.
  12. There could be multiple occurences of any given literal but the
  13. algorithm uses the first (eg earliest occurring) match.
  14. */
  15. bool matchWildcardPattern(const char *str, const char *pattern) {
  16. if (!pattern || !str)
  17. return false;
  18. /* Degenerate case: empty pattern always matches */
  19. if (*pattern=='\0')
  20. return true;
  21. /* Duplicate the pattern because we will need to change it */
  22. char *ptrndup = strdup(pattern);
  23. int plen = strlen(ptrndup);
  24. char *ptrnend = ptrndup+plen; /* Points to nil-terminator at end of pattern */
  25. char *beginLiteral, *endLiteral;
  26. const char *marker;
  27. bool fMatch = false;
  28. beginLiteral = ptrndup;
  29. // We will scan the source string starting from the beginning
  30. marker = str;
  31. while (true) {
  32. endLiteral = strchr(beginLiteral,'*');
  33. if (!endLiteral)
  34. endLiteral = ptrnend;
  35. // Overwrite asteriks with nil-character to terminate the substring
  36. *endLiteral = '\0';
  37. // Segment length does not include the nil-terminator
  38. size_t segmentLen = endLiteral-beginLiteral;
  39. // Search for current segment within the source string
  40. // Failure means that the pattern does not match-- BREAK the loop
  41. marker = strstr(marker, beginLiteral);
  42. if (!marker)
  43. break;
  44. // The first literal segment MUST appear at beginning of source string
  45. if (beginLiteral==ptrndup && marker!=str)
  46. break;
  47. // Found: advance pointer along the source string
  48. marker += segmentLen;
  49. // Restore the asterix in pattern
  50. *endLiteral = '*';
  51. // Move on to next literal in the pattern, which starts
  52. // after the asteriks in the current literal
  53. beginLiteral = endLiteral+1;
  54. // If we have matched all the literal sections in the pattern
  55. // then we have a match IFF
  56. // 1. End of source string is reached OR
  57. // 2. The pattern ends with an asterix
  58. if (beginLiteral>=ptrnend)
  59. {
  60. fMatch = (*marker=='\0') || (ptrnend[-1]=='*');
  61. break;
  62. }
  63. }
  64. free(ptrndup);
  65. return fMatch;
  66. }
  67. /*
  68. Implementation of P3PReference class
  69. */
  70. P3PReference::P3PReference(P3PCURL pszLocation) {
  71. pszPolicyAbout = strdup(pszLocation);
  72. pHead = NULL;
  73. fAllVerbs = true;
  74. }
  75. P3PReference::~P3PReference() {
  76. free(pszPolicyAbout);
  77. /* Free constraint list */
  78. Constraint *pc, *next=pHead;
  79. while (pc=next) {
  80. next = pc->pNext;
  81. delete pc;
  82. }
  83. }
  84. void P3PReference::addPathConstraint(P3PCURL pszSubtree, bool fInclude) {
  85. Constraint *pc = new Constraint();
  86. if (!pc)
  87. return;
  88. /* This is a path constraint */
  89. pc->fPath = TRUE;
  90. pc->pszPrefix = strdup(pszSubtree);
  91. pc->fInclude = fInclude ? TRUE : FALSE;
  92. addConstraint(pc);
  93. }
  94. void P3PReference::addConstraint(Constraint *pc) {
  95. /* Insert at beginning of linked list
  96. (Constraint ordering is not significant because they are evaluated
  97. until one fails) */
  98. pc->pNext = pHead;
  99. pHead = pc;
  100. }
  101. void P3PReference::include(P3PCURL pszSubtree) {
  102. addPathConstraint(pszSubtree, true);
  103. }
  104. void P3PReference::exclude(P3PCURL pszSubtree) {
  105. addPathConstraint(pszSubtree, false);
  106. }
  107. void P3PReference::addVerb(const char *pszVerb) {
  108. Constraint *pc = new Constraint();
  109. if (!pc)
  110. return;
  111. /* This is a verb constraint */
  112. pc->fPath = FALSE;
  113. pc->pszVerb = strdup(pszVerb);
  114. addConstraint(pc);
  115. fAllVerbs = false;
  116. }
  117. bool P3PReference::applies(P3PCURL pszAbsoluteURL, const char *pszVerb) {
  118. bool fVerbMatch = this->fAllVerbs;
  119. bool fPathMatch = false;
  120. /* Scan through the constraint list */
  121. for (Constraint *pc = pHead; pc; pc=pc->pNext) {
  122. if (pc->fPath) {
  123. bool fMatch = matchWildcardPattern(pszAbsoluteURL, pc->pszPrefix);
  124. /* If the constraint requires the URL to be excluded from that subtree,
  125. the pattern match must fail. Otherwise the constraint is not satisfied.
  126. If one path constraint is violated, we can return immediately.
  127. Otherwise the loop continues.
  128. */
  129. if (pc->fInclude && fMatch)
  130. fPathMatch = true;
  131. else if (!pc->fInclude && fMatch)
  132. return false;
  133. }
  134. else
  135. /* Otherwise this is a verb constraint */
  136. fVerbMatch = fVerbMatch || !stricmp(pc->pszVerb, pszVerb);
  137. }
  138. /* The reference applies only if the path constraint is satisfied
  139. (eg the given URL is included in at least one constraint and not
  140. excluded by any of the negative constraints) AND verb constraint
  141. is satisfied */
  142. return fPathMatch && fVerbMatch;
  143. }
  144. /*
  145. Implementation of P3PPolicyRef class
  146. */
  147. P3PPolicyRef::P3PPolicyRef() {
  148. pHead = pLast = NULL;
  149. ftExpires.dwLowDateTime = ftExpires.dwHighDateTime = 0x0;
  150. }
  151. P3PPolicyRef::~P3PPolicyRef() {
  152. for (P3PReference *temp, *pref = pHead; pref; ) {
  153. temp = pref->pNext;
  154. delete pref;
  155. pref = temp;
  156. }
  157. }
  158. void P3PPolicyRef::addReference(P3PReference *pref) {
  159. /* Order of references in a policy-ref files IS significant.
  160. The references must be added/evaluated in the same order as
  161. they appear in the XML document */
  162. if (pHead==NULL)
  163. pHead = pLast = pref;
  164. else {
  165. pLast->pNext = pref;
  166. pLast = pref;
  167. }
  168. pref->pNext = NULL;
  169. }
  170. P3PCURL P3PPolicyRef::mapResourceToPolicy(P3PCURL pszResource, const P3PVERB pszVerb) {
  171. for (P3PReference *pref = pHead; pref; pref=pref->pNext)
  172. if (pref->applies(pszResource, pszVerb))
  173. return pref->about();
  174. return NULL;
  175. }