File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / minires / ns_samedomain.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (12 years, 5 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>