Example #1
0
/* Copy an RDATA, using compression pointers where RFC1035 permits.
 */
static int
rdcpy(ns_newmsg *handle, ns_type type, const u_char *rdata, size_t rdlen) {
    ns_msg *msg = &handle->msg;
    u_char *p = (u_char *) (unsigned long) msg->_msg_ptr;
    u_char *t = p + NS_INT16SZ;
    u_char *s = t;
    int n;

    switch (type) {
    case ns_t_soa:
        /* MNAME. */
        n = ns_name_pack(rdata, t, msg->_eom - t,
                         handle->dnptrs, handle->lastdnptr);
        if (n < 0)
            return (-1);
        t += n;
        if (ns_name_skip(&rdata, msg->_eom) < 0)
            return (-1);

        /* ANAME. */
        n = ns_name_pack(rdata, t, msg->_eom - t,
                         handle->dnptrs, handle->lastdnptr);
        if (n < 0)
            return (-1);
        t += n;
        if (ns_name_skip(&rdata, msg->_eom) < 0)
            return (-1);

        /* Serial, Refresh, Retry, Expiry, and Minimum. */
        if ((msg->_eom - t) < (NS_INT32SZ * 5)) {
            errno = EMSGSIZE;
            return (-1);
        }
        memcpy(t, rdata, NS_INT32SZ * 5);
        t += (NS_INT32SZ * 5);
        break;
    case ns_t_ptr:
    case ns_t_cname:
    case ns_t_ns:
        /* PTRDNAME, CNAME, or NSDNAME. */
        n = ns_name_pack(rdata, t, msg->_eom - t,
                         handle->dnptrs, handle->lastdnptr);
        if (n < 0)
            return (-1);
        t += n;
        break;
    default:
        memcpy(t, rdata, rdlen);
        t += rdlen;
    }
    NS_PUT16(t - s, p);
    msg->_msg_ptr = t;
    return (0);
}
Example #2
0
/* Add a question (or zone, if it's an update) to a "newmsg" object.
 */
int
ns_newmsg_q(ns_newmsg *handle, ns_nname_ct qname,
            ns_type qtype, ns_class qclass)
{
    ns_msg *msg = &handle->msg;
    u_char *t;
    int n;

    if (msg->_sect != ns_s_qd) {
        errno = ENODEV;
        return (-1);
    }
    t = (u_char *) (unsigned long) msg->_msg_ptr;
    if (msg->_rrnum == 0)
        msg->_sections[ns_s_qd] = t;
    n = ns_name_pack(qname, t, msg->_eom - t,
                     handle->dnptrs, handle->lastdnptr);
    if (n < 0)
        return (-1);
    t += n;
    if (t + QFIXEDSZ >= msg->_eom) {
        errno = EMSGSIZE;
        return (-1);
    }
    NS_PUT16(qtype, t);
    NS_PUT16(qclass, t);
    msg->_msg_ptr = t;
    msg->_counts[ns_s_qd] = ++msg->_rrnum;
    return (0);
}
Example #3
0
/* Add an RR to a "newmsg" object.
 */
int
ns_newmsg_rr(ns_newmsg *handle, ns_sect sect,
             ns_nname_ct name, ns_type type,
             ns_class rr_class, u_int32_t ttl,
             u_int16_t rdlen, const u_char *rdata)
{
    ns_msg *msg = &handle->msg;
    u_char *t;
    int n;

    if (sect < msg->_sect) {
        errno = ENODEV;
        return (-1);
    }
    t = (u_char *) (unsigned long) msg->_msg_ptr;
    if (sect > msg->_sect) {
        msg->_sect = sect;
        msg->_sections[sect] = t;
        msg->_rrnum = 0;
    }
    n = ns_name_pack(name, t, msg->_eom - t,
                     handle->dnptrs, handle->lastdnptr);
    if (n < 0)
        return (-1);
    t += n;
    if (t + RRFIXEDSZ + rdlen >= msg->_eom) {
        errno = EMSGSIZE;
        return (-1);
    }
    NS_PUT16(type, t);
    NS_PUT16(rr_class, t);
    NS_PUT32(ttl, t);
    msg->_msg_ptr = t;
    if (rdcpy(handle, type, rdata, rdlen) < 0)
        return (-1);
    msg->_counts[sect] = ++msg->_rrnum;
    return (0);
}
Example #4
0
int
ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k,
	 const u_char *querysig, int querysiglen, u_char *sig, int *siglen,
	 time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr)
{
	HEADER *hp = (HEADER *)msg;
	DST_KEY *key = (DST_KEY *)k;
	u_char *cp, *eob;
	u_char *lenp;
	u_char *alg;
	int n;
	time_t timesigned;
        u_char name[NS_MAXCDNAME];

	dst_init();
	if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL)
		return (-1);

	cp = msg + *msglen;
	eob = msg + msgsize;

	/* Name. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		n = ns_name_pton(key->dk_key_name, name, sizeof name);
		if (n != -1)
			n = ns_name_pack(name, cp, eob - cp,
					 (const u_char **)dnptrs,
					 (const u_char **)lastdnptr);

	} else {
		n = ns_name_pton("", name, sizeof name);
		if (n != -1)
			n = ns_name_pack(name, cp, eob - cp, NULL, NULL);
	}
	if (n < 0)
		return (NS_TSIG_ERROR_NO_SPACE);
	cp += n;

	/* Type, class, ttl, length (not filled in yet). */
	BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ);
	PUTSHORT(ns_t_tsig, cp);
	PUTSHORT(ns_c_any, cp);
	PUTLONG(0, cp);		/*%< TTL */
	lenp = cp;
	cp += 2;

	/* Alg. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		if (key->dk_alg != KEY_HMAC_MD5)
			return (-ns_r_badkey);
		n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL);
	}
	else
		n = dn_comp("", cp, eob - cp, NULL, NULL);
	if (n < 0)
		return (NS_TSIG_ERROR_NO_SPACE);
	alg = cp;
	cp += n;
	
	/* Time. */
	BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
	PUTSHORT(0, cp);
	timesigned = time(NULL);
	if (error != ns_r_badtime)
		PUTLONG(timesigned, cp);
	else
		PUTLONG(in_timesigned, cp);
	PUTSHORT(NS_TSIG_FUDGE, cp);

	/* Compute the signature. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		void *ctx;
		u_char buf[NS_MAXCDNAME], *cp2;
		int n;

		dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0);

		/* Digest the query signature, if this is a response. */
		if (querysiglen > 0 && querysig != NULL) {
			u_int16_t len_n = htons(querysiglen);
			dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
				      (u_char *)&len_n, INT16SZ, NULL, 0);
			dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
				      querysig, querysiglen, NULL, 0);
		}

		/* Digest the message. */
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen,
			      NULL, 0);

		/* Digest the key name. */
		n = ns_name_ntol(name, buf, sizeof(buf));
		INSIST(n > 0);
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the class and TTL. */
		cp2 = buf;
		PUTSHORT(ns_c_any, cp2);
		PUTLONG(0, cp2);
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf,
			      NULL, 0);

		/* Digest the algorithm. */
		n = ns_name_ntol(alg, buf, sizeof(buf));
		INSIST(n > 0);
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the time signed, fudge, error, and other data */
		cp2 = buf;
		PUTSHORT(0, cp2);	/*%< Top 16 bits of time */
		if (error != ns_r_badtime)
			PUTLONG(timesigned, cp2);
		else
			PUTLONG(in_timesigned, cp2);
		PUTSHORT(NS_TSIG_FUDGE, cp2);
		PUTSHORT(error, cp2);	/*%< Error */
		if (error != ns_r_badtime)
			PUTSHORT(0, cp2);	/*%< Other data length */
		else {
			PUTSHORT(INT16SZ+INT32SZ, cp2);	/*%< Other data length */
			PUTSHORT(0, cp2);	/*%< Top 16 bits of time */
			PUTLONG(timesigned, cp2);
		}
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf,
			      NULL, 0);

		n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0,
				  sig, *siglen);
		if (n < 0)
			return (-ns_r_badkey);
		*siglen = n;
	} else
		*siglen = 0;

	/* Add the signature. */
	BOUNDS_CHECK(cp, INT16SZ + (*siglen));
	PUTSHORT(*siglen, cp);
	memcpy(cp, sig, *siglen);
	cp += (*siglen);

	/* The original message ID & error. */
	BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
	PUTSHORT(ntohs(hp->id), cp);	/*%< already in network order */
	PUTSHORT(error, cp);

	/* Other data. */
	BOUNDS_CHECK(cp, INT16SZ);
	if (error != ns_r_badtime)
		PUTSHORT(0, cp);	/*%< Other data length */
	else {
		PUTSHORT(INT16SZ+INT32SZ, cp);	/*%< Other data length */
		BOUNDS_CHECK(cp, INT32SZ+INT16SZ);
		PUTSHORT(0, cp);	/*%< Top 16 bits of time */
		PUTLONG(timesigned, cp);
	}

	/* Go back and fill in the length. */
	PUTSHORT(cp - lenp - INT16SZ, lenp);

	hp->arcount = htons(ntohs(hp->arcount) + 1);
	*msglen = (cp - msg);
	return (0);
}