int mesg_dname_cmp (u_char *msg, u_char *dname_mesg, u_char *dname) {

	/*
	 * compare dname_mesg and dname label by label, while doing
	 * decompression of the dname_mesg of the message msg.
	 */
	dname_mesg = dname_redirect (dname_mesg, msg);
	while (*dname_mesg != '\0' && (*dname == *dname_mesg)) {
		int len;

		len  = labellen(dname_mesg);
		if (len != labellen(dname))
			return -1;

		if (*dname == EDNS0_ELT_BITLABEL) {
			if (memcmp (dname_mesg + 1, dname + 1,  len))
				return -1;
		} else if (strncasecmp (dname_mesg + 1, dname + 1, len))
				return -1;

		dname += len + 1;
		dname_mesg += len + 1;
		dname_mesg = dname_redirect (dname_mesg, msg);
	}

	if (*dname != *dname_mesg)
		return -1;
	else
		return 0;
}
u_char *mesg_skip_dname (u_char *dname, u_char *end) {
	int l;

	if (dname >= end)
		return NULL;

	while(*dname) {
		if ((*dname & DNCMP_MASK) == DNCMP_MASK) {
			dname += 2;	/* redirection */
			return dname;
		}
		if (dname + 2 > end) /* we need at least 2 bytes */
			return NULL;

		l = labellen(dname);
		if (l < 0)
			return NULL;
		dname += l + 1;

		if (dname >= end)
			return NULL;
	}
	dname++;	/* push away null terminator */
	return dname;
}
Exemplo n.º 3
0
/*
 * ns_name_skip(ptrptr, eom)
 *  Advance *ptrptr to skip over the compressed name it points at.
 * return:
 *  0 on success, -1 (with errno set) on failure.
 */
static int
irc_ns_name_skip(const unsigned char **ptrptr, const unsigned char *eom)
{
  const unsigned char *cp;
  unsigned int n;
  int l;

  cp = *ptrptr;

  while (cp < eom && (n = *cp++) != 0)
  {
    /* Check for indirection. */
    switch (n & NS_CMPRSFLGS)
    {
      case 0: /* normal case, n == len */
        cp += n;
        continue;

      case NS_TYPE_ELT: /* EDNS0 extended label */
        if ((l = labellen(cp - 1)) < 0)
        {
          errno = EMSGSIZE; /* XXX */
          return (-1);
        }

        cp += l;
        continue;

      case NS_CMPRSFLGS: /* indirection */
        cp++;
        break;

      default: /* illegal type */
        errno = EMSGSIZE;
        return (-1);
    }

    break;
  }

  if (cp > eom)
  {
    errno = EMSGSIZE;
    return (-1);
  }

  *ptrptr = cp;
  return (0);
} /*2*/
Exemplo n.º 4
0
int
ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
{
	const u_char *cp;
	u_char *dn, *eom;
	u_char c;
	u_int n;
	int l;

	cp = src;
	dn = dst;
	eom = dst + dstsiz;

	if (dn >= eom) {
		errno = EMSGSIZE;
		return (-1);
	}
	while ((n = *cp++) != 0) {
		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
			/* Some kind of compression pointer. */
			errno = EMSGSIZE;
			return (-1);
		}
		*dn++ = n;
		if ((l = labellen(cp - 1)) < 0) {
			errno = EMSGSIZE;
			return (-1);
		}
		if (dn + l >= eom) {
			errno = EMSGSIZE;
			return (-1);
		}
		for ((void)NULL; l > 0; l--) {
			c = *cp++;
			if (isupper(c))
				*dn++ = tolower(c);
			else
				*dn++ = c;
		}
	}
	*dn++ = '\0';
	return (dn - dst);
}
Exemplo n.º 5
0
/*
 * irc_ns_name_ntop(src, dst, dstsiz)
 *	Convert an encoded domain name to printable ascii as per RFC1035.
 * return:
 *	Number of bytes written to buffer, or -1 (with errno set)
 * notes:
 *	The root is returned as "."
 *	All other domains are returned in non absolute form
 */
static int
irc_ns_name_ntop(const char *src, char *dst, size_t dstsiz)
{
	const char *cp;
	char *dn, *eom;
	unsigned char c;
	unsigned int n;
	int l;

	cp = src;
	dn = dst;
	eom = dst + dstsiz;

	while ((n = *cp++) != 0) {
		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
			/* Some kind of compression pointer. */
			errno = EMSGSIZE;
			return (-1);
		}
		if (dn != dst) {
			if (dn >= eom) {
				errno = EMSGSIZE;
				return (-1);
			}
			*dn++ = '.';
		}
		if ((l = labellen((const unsigned char*)(cp - 1))) < 0) {
			errno = EMSGSIZE; /* XXX */
			return(-1);
		}
		if (dn + l >= eom) {
			errno = EMSGSIZE;
			return (-1);
		}
		if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
			int m;

			if (n != DNS_LABELTYPE_BITSTRING) {
				/* XXX: labellen should reject this case */
				errno = EINVAL;
				return(-1);
			}
			if ((m = irc_decode_bitstring(&cp, dn, eom)) < 0)
			{
				errno = EMSGSIZE;
				return(-1);
			}
			dn += m;
			continue;
		}
		for ((void)NULL; l > 0; l--) {
			c = *cp++;
			if (special(c)) {
				if (dn + 1 >= eom) {
					errno = EMSGSIZE;
					return (-1);
				}
				*dn++ = '\\';
				*dn++ = (char)c;
			} else if (!printable(c)) {
				if (dn + 3 >= eom) {
					errno = EMSGSIZE;
					return (-1);
				}
				*dn++ = '\\';
				*dn++ = digits[c / 100];
				*dn++ = digits[(c % 100) / 10];
				*dn++ = digits[c % 10];
			} else {
				if (dn >= eom) {
					errno = EMSGSIZE;
					return (-1);
				}
				*dn++ = (char)c;
			}
		}
	}
	if (dn == dst) {
		if (dn >= eom) {
			errno = EMSGSIZE;
			return (-1);
		}
		*dn++ = '.';
	}
	if (dn >= eom) {
		errno = EMSGSIZE;
		return (-1);
	}
	*dn++ = '\0';
	return (dn - dst);
}
Exemplo n.º 6
0
/*
 * irc_ns_name_unpack(rmsg, eom, src, dst, dstsiz)
 *	Unpack a domain name from a message, source may be compressed.
 * return:
 *	-1 if it fails, or consumed octets if it succeeds.
 */
static int
irc_ns_name_unpack(const unsigned char *rmsg, const unsigned char *eom,
                   const unsigned char *src, unsigned char *dst,
                   size_t dstsiz)
{
	const unsigned char *srcp, *dstlim;
	unsigned char *dstp;
	int n, len, checked, l;

	len = -1;
	checked = 0;
	dstp = dst;
	srcp = src;
	dstlim = dst + dstsiz;
	if (srcp < rmsg || srcp >= eom) {
		errno = EMSGSIZE;
		return (-1);
	}
	/* Fetch next label in domain name. */
	while ((n = *srcp++) != 0) {
		/* Check for indirection. */
		switch (n & NS_CMPRSFLGS) {
		case 0:
		case NS_TYPE_ELT:
			/* Limit checks. */
			if ((l = labellen(srcp - 1)) < 0) {
				errno = EMSGSIZE;
				return(-1);
			}
			if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
				errno = EMSGSIZE;
				return (-1);
			}
			checked += l + 1;
			*dstp++ = n;
			memcpy(dstp, srcp, l);
			dstp += l;
			srcp += l;
			break;

		case NS_CMPRSFLGS:
			if (srcp >= eom) {
				errno = EMSGSIZE;
				return (-1);
			}
			if (len < 0)
				len = srcp - src + 1;
			srcp = rmsg + (((n & 0x3f) << 8) | (*srcp & 0xff));
			if (srcp < rmsg || srcp >= eom) {  /* Out of range. */
				errno = EMSGSIZE;
				return (-1);
			}
			checked += 2;
			/*
			 * Check for loops in the compressed name;
			 * if we've looked at the whole message,
			 * there must be a loop.
			 */
			if (checked >= eom - rmsg) {
				errno = EMSGSIZE;
				return (-1);
			}
			break;

		default:
			errno = EMSGSIZE;
			return (-1);			/* flag error */
		}
	}
	*dstp = '\0';
	if (len < 0)
		len = srcp - src;
	return (len);
}
u_char *dname_decompress (u_char *buf, int buflen, u_char *dname,
			  u_char *m_head, u_char *m_tail, int *written) {
	int token_len, written_len, iter;
	u_char *cp, *next;
	int pktsiz = m_tail - m_head;

	next = NULL;
	written_len = token_len = 0;
	for (cp = dname; *cp; cp += token_len) {
		iter = 0;
	  top:
		if ((*cp & DNCMP_MASK) == DNCMP_MASK) {
			uint16_t ui;

			if (iter++ >= pktsiz) /* we're probably in a loop. */
				return NULL;

			if (!m_head || !m_tail) /* irregular redirect */
				return NULL;

			/* redirect */
			next = cp + 2;
			GETSHORT (ui, cp);
			ui = ui & ~DNCMP_MASK_INT16T;

			cp = m_head + ui;
			if (cp < m_head || m_tail < cp)
				return NULL;

			goto top;
		}

		token_len = labellen(cp);
		if (token_len < 0)
			return NULL;
		else
			token_len++;

		if (T.debug > 4)
			syslog (LOG_DEBUG, "token_len: %d", token_len);

		if (written_len + token_len >= buflen)
			return NULL; /* buffer overrun */
		if (cp + token_len > m_tail)
			return NULL; /* out of bounds */

		if (written) {
			/* non-printable dname string */
			memcpy (buf, cp, token_len);
			written_len += token_len;
			buf += token_len;
		} else {
			/* write printable string */
			if ((*cp & DNCMP_MASK) != EDNS0_MASK) {
				memcpy (buf, cp + 1, token_len - 1);
				*(buf + (token_len - 1)) = DNAME_DELIM;
				written_len += token_len;
				buf += token_len;
			} else if (*cp == EDNS0_ELT_BITLABEL) {
				int bitlength, i;
				u_char *wp;

				/* a bit conservative test, but simple */
				if (written_len + token_len*2 + 7 >= buflen)
					return NULL; /* buffer overrun */

				wp = buf;
				wp += sprintf(wp, "\\[x");
				for (i = 1; i < token_len-1; i++) {
					u_char d1, d2;
					uint b;

					b = (int) *(cp + 1 + i);
					d1 = hex[(b >> 4) & 0x0f];
					d2 = hex[b & 0x0f];
					wp += sprintf(wp, "%c%c", d1, d2);
				}
				bitlength = *(cp + 1) ? *(cp + 1) : 256;
				wp += sprintf(wp, "/%u].", bitlength);

				written_len += (wp - buf);
				buf += written_len;
			}
		}
	}
Exemplo n.º 8
0
/*%
 *	Pack domain name 'domain' into 'comp_dn'.
 *
 * return:
 *\li	Size of the compressed name, or -1.
 *
 * notes:
 *\li	'dnptrs' is an array of pointers to previous compressed names.
 *\li	dnptrs[0] is a pointer to the beginning of the message. The array
 *	ends with NULL.
 *\li	'lastdnptr' is a pointer to the end of the array pointed to
 *	by 'dnptrs'.
 *
 * Side effects:
 *\li	The list of pointers in dnptrs is updated for labels inserted into
 *	the message as we compress the name.  If 'dnptr' is NULL, we don't
 *	try to compress names. If 'lastdnptr' is NULL, we don't update the
 *	list.
 */
int
ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
	     const u_char **dnptrs, const u_char **lastdnptr)
{
	u_char *dstp;
	const u_char **cpp, **lpp, *eob, *msg;
	const u_char *srcp;
	int n, l, first = 1;

	srcp = src;
	dstp = dst;
	eob = dstp + dstsiz;
	lpp = cpp = NULL;
	if (dnptrs != NULL) {
		if ((msg = *dnptrs++) != NULL) {
			for (cpp = dnptrs; *cpp != NULL; cpp++)
				(void)NULL;
			lpp = cpp;	/*%< end of list to search */
		}
	} else
		msg = NULL;

	/* make sure the domain we are about to add is legal */
	l = 0;
	do {
		int l0;

		n = *srcp;
		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
			errno = EMSGSIZE;
			return (-1);
		}
		if ((l0 = labellen(srcp)) < 0) {
			errno = EINVAL;
			return(-1);
		}
		l += l0 + 1;
		if (l > MAXCDNAME) {
			errno = EMSGSIZE;
			return (-1);
		}
		srcp += l0 + 1;
	} while (n != 0);

	/* from here on we need to reset compression pointer array on error */
	srcp = src;
	do {
		/* Look to see if we can use pointers. */
		n = *srcp;
		if (n != 0 && msg != NULL) {
			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
				    (const u_char * const *)lpp);
			if (l >= 0) {
				if (dstp + 1 >= eob) {
					goto cleanup;
				}
				*dstp++ = (l >> 8) | NS_CMPRSFLGS;
				*dstp++ = l % 256;
				return (dstp - dst);
			}
			/* Not found, save it. */
			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
			    (dstp - msg) < 0x4000 && first) {
				*cpp++ = dstp;
				*cpp = NULL;
				first = 0;
			}
		}
		/* copy label to buffer */
		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
			/* Should not happen. */
			goto cleanup;
		}
		n = labellen(srcp);
		if (dstp + 1 + n >= eob) {
			goto cleanup;
		}
		memcpy(dstp, srcp, n + 1);
		srcp += n + 1;
		dstp += n + 1;
	} while (n != 0);