Exemplo n.º 1
0
u_char *
ns_find_tsig(u_char *msg, u_char *eom) {
	HEADER *hp = (HEADER *)msg;
	int n, type;
	u_char *cp = msg, *start;
	isc_result_t status;

	if (msg == NULL || eom == NULL || msg > eom)
		return (NULL);

	if (cp + HFIXEDSZ >= eom)
		return (NULL);

	if (hp->arcount == 0)
		return (NULL);

	cp += HFIXEDSZ;

	status = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount), &n);
	if (status != ISC_R_SUCCESS)
		return (NULL);
	cp += n;

	status = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount), &n);
	if (status != ISC_R_SUCCESS)
		return (NULL);
	cp += n;

	status = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount), &n);
	if (status != ISC_R_SUCCESS)
		return (NULL);
	cp += n;

	status = ns_skiprr(cp, eom, ns_s_ar, ntohs(hp->arcount) - 1, &n);
	if (status != ISC_R_SUCCESS)
		return (NULL);
	cp += n;

	start = cp;
	n = dn_skipname(cp, eom);
	if (n < 0)
		return (NULL);
	cp += n;
	if (cp + INT16SZ >= eom)
		return (NULL);

	GETSHORT(type, cp);
	if (type != ns_t_tsig)
		return (NULL);
	return (start);
}
Exemplo n.º 2
0
int
ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
    const u_char *eom = msg + msglen;
    int i;

    handle->_msg = msg;
    handle->_eom = eom;
    if (msg + NS_INT16SZ > eom)
        RETERR(EMSGSIZE);
    NS_GET16(handle->_id, msg);
    if (msg + NS_INT16SZ > eom)
        RETERR(EMSGSIZE);
    NS_GET16(handle->_flags, msg);
    for (i = 0; i < ns_s_max; i++) {
        if (msg + NS_INT16SZ > eom)
            RETERR(EMSGSIZE);
        NS_GET16(handle->_counts[i], msg);
    }
    for (i = 0; i < ns_s_max; i++)
        if (handle->_counts[i] == 0)
            handle->_sections[i] = NULL;
        else {
            int b = ns_skiprr(msg, eom, (ns_sect)i,
                              handle->_counts[i]);

            if (b < 0)
                return (-1);
            handle->_sections[i] = msg;
            msg += b;
        }
    if (msg != eom)
        RETERR(EMSGSIZE);
    setsection(handle, ns_s_max);
    return (0);
}
Exemplo n.º 3
0
int
ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
    int b;
    int tmp;

    /* Make section right. */
    tmp = section;
    if (tmp < 0 || section >= ns_s_max)
        RETERR(ENODEV);
    if (section != handle->_sect)
        setsection(handle, section);

    /* Make rrnum right. */
    if (rrnum == -1)
        rrnum = handle->_rrnum;
    if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
        RETERR(ENODEV);
    if (rrnum < handle->_rrnum)
        setsection(handle, section);
    if (rrnum > handle->_rrnum) {
        b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
                      rrnum - handle->_rrnum);

        if (b < 0)
            return (-1);
        handle->_msg_ptr += b;
        handle->_rrnum = rrnum;
    }

    /* Do the parse. */
    b = dn_expand(handle->_msg, handle->_eom,
                  handle->_msg_ptr, rr->name, NS_MAXDNAME);
    if (b < 0)
        return (-1);
    handle->_msg_ptr += b;
    if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
        RETERR(EMSGSIZE);
    NS_GET16(rr->type, handle->_msg_ptr);
    NS_GET16(rr->rr_class, handle->_msg_ptr);
    if (section == ns_s_qd) {
        rr->ttl = 0;
        rr->rdlength = 0;
        rr->rdata = NULL;
    } else {
        if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
            RETERR(EMSGSIZE);
        NS_GET32(rr->ttl, handle->_msg_ptr);
        NS_GET16(rr->rdlength, handle->_msg_ptr);
        if (handle->_msg_ptr + rr->rdlength > handle->_eom)
            RETERR(EMSGSIZE);
        rr->rdata = handle->_msg_ptr;
        handle->_msg_ptr += rr->rdlength;
    }
    if (++handle->_rrnum > handle->_counts[(int)section])
        setsection(handle, (ns_sect)((int)section + 1));

    /* All done. */
    return (0);
}
Exemplo n.º 4
0
isc_result_t
ns_initparse(const u_char *msg, unsigned msglen, ns_msg *handle) {
	const u_char *eom = msg + msglen;
	int i;

	memset(handle, 0x5e, sizeof *handle);
	handle->_msg = msg;
	handle->_eom = eom;
	if (msg + NS_INT16SZ > eom)
		return ISC_R_INCOMPLETE;
	handle->_id = getUShort (msg);
	msg += 2;
	if (msg + NS_INT16SZ > eom)
		return ISC_R_INCOMPLETE;
	handle->_flags = getUShort (msg);
	msg += 2;
	for (i = 0; i < ns_s_max; i++) {
		if (msg + NS_INT16SZ > eom)
			return ISC_R_INCOMPLETE;
		handle->_counts[i] = getUShort (msg);
		msg += 2;
	}
	for (i = 0; i < ns_s_max; i++)
		if (handle->_counts[i] == 0)
			handle->_sections[i] = NULL;
		else {
			int b;
			isc_result_t status =
				ns_skiprr(msg, eom, (ns_sect)i,
					  handle->_counts[i], &b);

			if (status != ISC_R_SUCCESS)
				return STATUS;
			handle->_sections[i] = msg;
			msg += b;
		}
	if (msg != eom)
		return ISC_R_INCOMPLETE;
	setsection(handle, ns_s_max);
	return ISC_R_SUCCESS;
}
Exemplo n.º 5
0
isc_result_t
ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
	int b;
	isc_result_t status;
	int tmp; /* XXX used to force a signed comparison below */

	/* Make section right. */
	if ((tmp = section) < 0 || section >= ns_s_max)
		return ISC_R_NOTIMPLEMENTED;
	if (section != handle->_sect)
		setsection(handle, section);

	/* Make rrnum right. */
	if (rrnum == -1)
		rrnum = handle->_rrnum;
	if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
		return ISC_R_UNKNOWNATTRIBUTE;
	if (rrnum < handle->_rrnum)
		setsection(handle, section);
	if (rrnum > handle->_rrnum) {
		status = ns_skiprr(handle->_ptr, handle->_eom, section,
			      rrnum - handle->_rrnum, &b);

		if (status != ISC_R_SUCCESS)
			return status;
		handle->_ptr += b;
		handle->_rrnum = rrnum;
	}

	/* Do the parse. */
	b = dn_expand(handle->_msg, handle->_eom,
		      handle->_ptr, rr->name, NS_MAXDNAME);
	if (b < 0)
		return ISC_R_FORMERR;
	handle->_ptr += b;
	if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
		return ISC_R_INCOMPLETE;
	rr->type = getUShort (handle->_ptr);
	handle -> _ptr += 2;
	rr->rr_class = getUShort (handle->_ptr);
	handle -> _ptr += 2;
	if (section == ns_s_qd) {
		rr->ttl = 0;
		rr->rdlength = 0;
		rr->rdata = NULL;
	} else {
		if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
			return ISC_R_INCOMPLETE;
		rr->ttl = getULong (handle->_ptr);
		handle -> _ptr += 4;
		rr->rdlength = getUShort (handle->_ptr);
		handle -> _ptr += 2;
		if (handle->_ptr + rr->rdlength > handle->_eom)
			return ISC_R_INCOMPLETE;
		rr->rdata = handle->_ptr;
		handle->_ptr += rr->rdlength;
	}
	if (++handle->_rrnum > handle->_counts[(int)section])
		setsection(handle, (ns_sect)((int)section + 1));

	/* All done. */
	return ISC_R_SUCCESS;
}
Exemplo n.º 6
0
/*
 * Simplified version of srv_query() for domain auto-discovery.
 */
int
srv_getdom(res_state state, const char *svc_name, char **rrname)
{
	union {
		HEADER hdr;
		uchar_t buf[NS_MAXMSG];
	} msg;
	int len, qdcount, ancount;
	uchar_t *ptr, *eom;
	char namebuf[NS_MAXDNAME];

	/* query necessary resource records */

	*rrname = NULL;
	if (DBG(DNS, 1))  {
		logger(LOG_DEBUG, "Looking for SRV RRs '%s.*'", svc_name);
	}
	len = res_nsearch(state, svc_name, C_IN, T_SRV,
	    msg.buf, sizeof (msg.buf));
	if (len < 0) {
		if (DBG(DNS, 0)) {
			logger(LOG_DEBUG,
			    "DNS search for '%s' failed (%s)",
			    svc_name, hstrerror(state->res_h_errno));
		}
		return (-1);
	}

	if (len > sizeof (msg.buf)) {
		logger(LOG_WARNING,
		    "DNS query %ib message doesn't fit into %ib buffer",
		    len, sizeof (msg.buf));
		len = sizeof (msg.buf);
	}

	/* parse the reply header */

	ptr = msg.buf + sizeof (msg.hdr);
	eom = msg.buf + len;
	qdcount = ntohs(msg.hdr.qdcount);
	ancount = ntohs(msg.hdr.ancount);

	/* skip the question section */

	len = ns_skiprr(ptr, eom, ns_s_qd, qdcount);
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		return (-1);
	}
	ptr += len;

	/* parse the answer section */
	if (ancount < 1) {
		logger(LOG_ERR, "DNS query - no answers");
		return (-1);
	}

	len = dn_expand(msg.buf, eom, ptr, namebuf, sizeof (namebuf));
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		return (-1);
	}
	*rrname = strdup(namebuf);
	if (*rrname == NULL) {
		logger(LOG_ERR, "Out of memory");
		return (-1);
	}

	return (0);
}
Exemplo n.º 7
0
static ad_disc_cds_t *
srv_parse(uchar_t *msg, int len, int *scnt, int *maxcnt)
{
	ad_disc_cds_t *cds;
	ad_disc_cds_t *cds_res = NULL;
	HEADER *hdr;
	int i, qdcount, ancount, nscount, arcount;
	uchar_t *ptr, *eom;
	uchar_t *end;
	uint16_t type;
	/* LINTED  E_FUNC_SET_NOT_USED */
	uint16_t class __unused;
	uint32_t rttl;
	uint16_t size;
	char namebuf[NS_MAXDNAME];

	eom = msg + len;
	hdr = (void *)msg;
	ptr = msg + sizeof (HEADER);

	qdcount = ntohs(hdr->qdcount);
	ancount = ntohs(hdr->ancount);
	nscount = ntohs(hdr->nscount);
	arcount = ntohs(hdr->arcount);

	/* skip the question section */

	len = ns_skiprr(ptr, eom, ns_s_qd, qdcount);
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		return (NULL);
	}
	ptr += len;

	/*
	 * Walk through the answer section, building the result array.
	 * The array size is +2 because we (possibly) add the preferred
	 * DC if it was not there, and an empty one (null termination).
	 */

	*maxcnt = ancount + 2;
	cds_res = calloc(*maxcnt, sizeof (*cds_res));
	if (cds_res == NULL) {
		logger(LOG_ERR, "Out of memory");
		return (NULL);
	}

	cds = cds_res;
	for (i = 0; i < ancount; i++) {

		len = dn_expand(msg, eom, ptr, namebuf,
		    sizeof (namebuf));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		ptr += len;
		NS_GET16(type, ptr);
		NS_GET16(class, ptr);
		NS_GET32(rttl, ptr);
		NS_GET16(size, ptr);
		if ((end = ptr + size) > eom) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}

		if (type != T_SRV) {
			ptr = end;
			continue;
		}

		NS_GET16(cds->cds_ds.priority, ptr);
		NS_GET16(cds->cds_ds.weight, ptr);
		NS_GET16(cds->cds_ds.port, ptr);
		len = dn_expand(msg, eom, ptr, cds->cds_ds.host,
		    sizeof (cds->cds_ds.host));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid SRV record");
			goto err;
		}

		cds->cds_ds.ttl = rttl;

		if (DBG(DNS, 2)) {
			logger(LOG_DEBUG, "    %s", namebuf);
			logger(LOG_DEBUG,
			    "        ttl=%d pri=%d weight=%d %s:%d",
			    rttl, cds->cds_ds.priority, cds->cds_ds.weight,
			    cds->cds_ds.host, cds->cds_ds.port);
		}
		cds++;

		/* move ptr to the end of current record */
		ptr = end;
	}
	*scnt = (cds - cds_res);

	/* skip the nameservers section (if any) */

	len = ns_skiprr(ptr, eom, ns_s_ns, nscount);
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		goto err;
	}
	ptr += len;

	/* walk through the additional records */
	for (i = 0; i < arcount; i++) {
		sa_family_t af;

		len = dn_expand(msg, eom, ptr, namebuf,
		    sizeof (namebuf));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		ptr += len;
		NS_GET16(type, ptr);
		NS_GET16(class, ptr);
		NS_GET32(rttl, ptr);
		NS_GET16(size, ptr);
		if ((end = ptr + size) > eom) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		switch (type) {
		case ns_t_a:
			af = AF_INET;
			break;
		case ns_t_aaaa:
			af = AF_INET6;
			break;
		default:
			continue;
		}

		if (DBG(DNS, 2)) {
			char abuf[INET6_ADDRSTRLEN];
			const char *ap;

			ap = inet_ntop(af, ptr, abuf, sizeof (abuf));
			logger(LOG_DEBUG, "    %s    %s    %s",
			    (af == AF_INET) ? "A   " : "AAAA",
			    (ap) ? ap : "?", namebuf);
		}

		/* Find the server, add to its address list. */
		for (cds = cds_res; cds->cds_ds.host[0] != '\0'; cds++)
			if (0 == strcmp(namebuf, cds->cds_ds.host))
				save_addr(cds, af, ptr, size);

		/* move ptr to the end of current record */
		ptr = end;
	}

	return (cds_res);

err:
	free(cds_res);
	return (NULL);
}