ns_samedomain.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (c) 1995,1999 by Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
  10. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
  11. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
  12. * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  15. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  16. * SOFTWARE.
  17. */
  18. #include <sys/types.h>
  19. #include <arpa/nameser.h>
  20. #include <errno.h>
  21. #include <string.h>
  22. /*%
  23. * Check whether a name belongs to a domain.
  24. *
  25. * Inputs:
  26. *\li a - the domain whose ancestry is being verified
  27. *\li b - the potential ancestor we're checking against
  28. *
  29. * Return:
  30. *\li boolean - is a at or below b?
  31. *
  32. * Notes:
  33. *\li Trailing dots are first removed from name and domain.
  34. * Always compare complete subdomains, not only whether the
  35. * domain name is the trailing string of the given name.
  36. *
  37. *\li "host.foobar.top" lies in "foobar.top" and in "top" and in ""
  38. * but NOT in "bar.top"
  39. */
  40. int
  41. ns_samedomain(const char *a, const char *b) {
  42. size_t la, lb;
  43. int diff, i, escaped;
  44. const char *cp;
  45. la = strlen(a);
  46. lb = strlen(b);
  47. /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
  48. if (la != 0U && a[la - 1] == '.') {
  49. escaped = 0;
  50. /* Note this loop doesn't get executed if la==1. */
  51. for (i = la - 2; i >= 0; i--)
  52. if (a[i] == '\\') {
  53. if (escaped)
  54. escaped = 0;
  55. else
  56. escaped = 1;
  57. } else
  58. break;
  59. if (!escaped)
  60. la--;
  61. }
  62. /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
  63. if (lb != 0U && b[lb - 1] == '.') {
  64. escaped = 0;
  65. /* note this loop doesn't get executed if lb==1 */
  66. for (i = lb - 2; i >= 0; i--)
  67. if (b[i] == '\\') {
  68. if (escaped)
  69. escaped = 0;
  70. else
  71. escaped = 1;
  72. } else
  73. break;
  74. if (!escaped)
  75. lb--;
  76. }
  77. /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
  78. if (lb == 0U)
  79. return (1);
  80. /* 'b' longer than 'a' means 'a' can't be in 'b'. */
  81. if (lb > la)
  82. return (0);
  83. /* 'a' and 'b' being equal at this point indicates sameness. */
  84. if (lb == la)
  85. return (strncasecmp(a, b, lb) == 0);
  86. /* Ok, we know la > lb. */
  87. diff = la - lb;
  88. /*
  89. * If 'a' is only 1 character longer than 'b', then it can't be
  90. * a subdomain of 'b' (because of the need for the '.' label
  91. * separator).
  92. */
  93. if (diff < 2)
  94. return (0);
  95. /*
  96. * If the character before the last 'lb' characters of 'b'
  97. * isn't '.', then it can't be a match (this lets us avoid
  98. * having "foobar.com" match "bar.com").
  99. */
  100. if (a[diff - 1] != '.')
  101. return (0);
  102. /*
  103. * We're not sure about that '.', however. It could be escaped
  104. * and thus not a really a label separator.
  105. */
  106. escaped = 0;
  107. for (i = diff - 2; i >= 0; i--)
  108. if (a[i] == '\\') {
  109. if (escaped)
  110. escaped = 0;
  111. else
  112. escaped = 1;
  113. } else
  114. break;
  115. if (escaped)
  116. return (0);
  117. /* Now compare aligned trailing substring. */
  118. cp = a + diff;
  119. return (strncasecmp(cp, b, lb) == 0);
  120. }
  121. libresolv_hidden_def (ns_samedomain)
  122. /*%
  123. * is "a" a subdomain of "b"?
  124. */
  125. int
  126. ns_subdomain(const char *a, const char *b) {
  127. return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
  128. }
  129. /*%
  130. * make a canonical copy of domain name "src"
  131. *
  132. * notes:
  133. * \code
  134. * foo -> foo.
  135. * foo. -> foo.
  136. * foo.. -> foo.
  137. * foo\. -> foo\..
  138. * foo\\. -> foo\\.
  139. * \endcode
  140. */
  141. int
  142. ns_makecanon(const char *src, char *dst, size_t dstsize) {
  143. size_t n = strlen(src);
  144. if (n + sizeof "." > dstsize) { /*%< Note: sizeof == 2 */
  145. __set_errno (EMSGSIZE);
  146. return (-1);
  147. }
  148. strcpy(dst, src);
  149. while (n >= 1U && dst[n - 1] == '.') /*%< Ends in "." */
  150. if (n >= 2U && dst[n - 2] == '\\' && /*%< Ends in "\." */
  151. (n < 3U || dst[n - 3] != '\\')) /*%< But not "\\." */
  152. break;
  153. else
  154. dst[--n] = '\0';
  155. dst[n++] = '.';
  156. dst[n] = '\0';
  157. return (0);
  158. }
  159. libresolv_hidden_def (ns_makecanon)
  160. /*%
  161. * determine whether domain name "a" is the same as domain name "b"
  162. *
  163. * return:
  164. *\li -1 on error
  165. *\li 0 if names differ
  166. *\li 1 if names are the same
  167. */
  168. int
  169. ns_samename(const char *a, const char *b) {
  170. char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
  171. if (ns_makecanon(a, ta, sizeof ta) < 0 ||
  172. ns_makecanon(b, tb, sizeof tb) < 0)
  173. return (-1);
  174. if (strcasecmp(ta, tb) == 0)
  175. return (1);
  176. else
  177. return (0);
  178. }
  179. libresolv_hidden_def (ns_samename)
  180. /*! \file */