[BACK]Return to ns_samedomain.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / nameser

Annotation of src/lib/libc/nameser/ns_samedomain.c, Revision 1.5

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

CVSweb <webmaster@jp.NetBSD.org>