(linenum→info "unix/slp.c:2238")

glibc/2.7/resolv/ns_samedomain.c

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