Annotation of embedaddon/dhcp/minires/ns_samedomain.c, revision 1.1.1.1

1.1       misho       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
1.1.1.1 ! misho      25: static const char rcsid[] = "$Id: ns_samedomain.c,v 1.4.786.2 2009/07/24 22:04:52 sar Exp $";
1.1       misho      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>