(root)/
glibc-2.38/
resolv/
ns_samedomain.c
       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  
      19  #include <sys/types.h>
      20  #include <arpa/nameser.h>
      21  #include <errno.h>
      22  #include <string.h>
      23  
      24  /*%
      25   *	Check whether a name belongs to a domain.
      26   *
      27   * Inputs:
      28   *\li	a - the domain whose ancestry is being verified
      29   *\li	b - the potential ancestor we're checking against
      30   *
      31   * Return:
      32   *\li	boolean - is a at or below b?
      33   *
      34   * Notes:
      35   *\li	Trailing dots are first removed from name and domain.
      36   *	Always compare complete subdomains, not only whether the
      37   *	domain name is the trailing string of the given name.
      38   *
      39   *\li	"host.foobar.top" lies in "foobar.top" and in "top" and in ""
      40   *	but NOT in "bar.top"
      41   */
      42  
      43  int
      44  ns_samedomain(const char *a, const char *b) {
      45  	size_t la, lb;
      46  	int diff, i, escaped;
      47  	const char *cp;
      48  
      49  	la = strlen(a);
      50  	lb = strlen(b);
      51  
      52  	/* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
      53  	if (la != 0U && a[la - 1] == '.') {
      54  		escaped = 0;
      55  		/* Note this loop doesn't get executed if la==1. */
      56  		for (i = la - 2; i >= 0; i--)
      57  			if (a[i] == '\\') {
      58  				if (escaped)
      59  					escaped = 0;
      60  				else
      61  					escaped = 1;
      62  			} else
      63  				break;
      64  		if (!escaped)
      65  			la--;
      66  	}
      67  
      68  	/* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
      69  	if (lb != 0U && b[lb - 1] == '.') {
      70  		escaped = 0;
      71  		/* note this loop doesn't get executed if lb==1 */
      72  		for (i = lb - 2; i >= 0; i--)
      73  			if (b[i] == '\\') {
      74  				if (escaped)
      75  					escaped = 0;
      76  				else
      77  					escaped = 1;
      78  			} else
      79  				break;
      80  		if (!escaped)
      81  			lb--;
      82  	}
      83  
      84  	/* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
      85  	if (lb == 0U)
      86  		return (1);
      87  
      88  	/* 'b' longer than 'a' means 'a' can't be in 'b'. */
      89  	if (lb > la)
      90  		return (0);
      91  
      92  	/* 'a' and 'b' being equal at this point indicates sameness. */
      93  	if (lb == la)
      94  		return (strncasecmp(a, b, lb) == 0);
      95  
      96  	/* Ok, we know la > lb. */
      97  
      98  	diff = la - lb;
      99  
     100  	/*
     101  	 * If 'a' is only 1 character longer than 'b', then it can't be
     102  	 * a subdomain of 'b' (because of the need for the '.' label
     103  	 * separator).
     104  	 */
     105  	if (diff < 2)
     106  		return (0);
     107  
     108  	/*
     109  	 * If the character before the last 'lb' characters of 'b'
     110  	 * isn't '.', then it can't be a match (this lets us avoid
     111  	 * having "foobar.com" match "bar.com").
     112  	 */
     113  	if (a[diff - 1] != '.')
     114  		return (0);
     115  
     116  	/*
     117  	 * We're not sure about that '.', however.  It could be escaped
     118           * and thus not a really a label separator.
     119  	 */
     120  	escaped = 0;
     121  	for (i = diff - 2; i >= 0; i--)
     122  		if (a[i] == '\\') {
     123  			if (escaped)
     124  				escaped = 0;
     125  			else
     126  				escaped = 1;
     127  		} else
     128  			break;
     129  	if (escaped)
     130  		return (0);
     131  
     132  	/* Now compare aligned trailing substring. */
     133  	cp = a + diff;
     134  	return (strncasecmp(cp, b, lb) == 0);
     135  }
     136  libresolv_hidden_def (ns_samedomain)
     137  
     138  /*%
     139   *	is "a" a subdomain of "b"?
     140   */
     141  int
     142  ns_subdomain (const char *a, const char *b)
     143  {
     144    return __libc_ns_samename (a, b) != 1 && ns_samedomain (a, b);
     145  }
     146  
     147  /*! \file */