Exemplo n.º 1
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);
}
Exemplo n.º 2
0
static void put_bn(BIGNUM *bn, u_char **pp)
{
   short i;

   i = BN_num_bits(bn);
   NS_PUT16(i, *pp);
   *pp+=BN_bn2bin(bn, *pp);
}
Exemplo n.º 3
0
/* Complete a "newmsg" object and return its size for use in write().
 * (Note: the "newmsg" object is also made ready for ns_parserr() etc.)
 */
size_t
ns_newmsg_done(ns_newmsg *handle) {
    ns_msg *msg = &handle->msg;
    ns_sect sect;
    u_char *t;

    t = (u_char *) (unsigned long) msg->_msg;
    NS_PUT16(msg->_id, t);
    NS_PUT16(msg->_flags, t);
    for (sect = 0; sect < ns_s_max; sect++)
        NS_PUT16(msg->_counts[sect], t);
    msg->_eom = msg->_msg_ptr;
    msg->_sect = ns_s_max;
    msg->_rrnum = -1;
    msg->_msg_ptr = NULL;
    return (msg->_eom - msg->_msg);
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
0
void
ns_put16(uint16_t src, u_char *dst) {
	NS_PUT16(src, dst);
}
Exemplo n.º 7
0
/*
 * Form update packets.
 * Returns the size of the resulting packet if no error
 * On error,
 *	returns -1 if error in reading a word/number in rdata
 *		   portion for update packets
 *		-2 if length of buffer passed is insufficient
 *		-3 if zone section is not the first section in
 *		   the linked list, or section order has a problem
 *		-4 on a number overflow
 *		-5 unknown operation or no records
 */
int
res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) {
	ns_updrec *rrecp_start = rrecp_in;
	HEADER *hp;
	u_char *cp, *sp1, *sp2, *startp, *endp;
	int n, i, soanum, multiline;
	ns_updrec *rrecp;
	struct in_addr ina;
	struct in6_addr in6a;
        char buf2[NS_MAXDNAME];
	u_char buf3[NS_MAXDNAME];
	int section, numrrs = 0, counts[ns_s_max];
	u_int16_t rtype, rclass;
	u_int32_t n1, rttl;
	u_char *dnptrs[20], **dpp, **lastdnptr;
	int siglen, keylen, certlen;

	/*
	 * Initialize header fields.
	 */
	if ((buf == NULL) || (buflen < NS_HFIXEDSZ))
		return (-1);
	memset(buf, 0, NS_HFIXEDSZ);
	hp = (HEADER *) buf;
#ifdef __APPLE__
	hp->id = res_randomid();
#else
	hp->id = htons(++statp->id);
#endif
	hp->opcode = ns_o_update;
	hp->rcode = ns_r_noerror;
	sp1 = buf + 2*NS_INT16SZ;  /* save pointer to zocount */
	cp = buf + NS_HFIXEDSZ;
	buflen -= NS_HFIXEDSZ;
	dpp = dnptrs;
	*dpp++ = buf;
	*dpp++ = NULL;
	lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];

	if (rrecp_start == NULL)
		return (-5);
	else if (rrecp_start->r_section != ns_s_zn)
		return (-3);

	memset(counts, 0, sizeof counts);
	for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) {
		numrrs++;
                section = rrecp->r_section;
		if (section < 0 || section >= ns_s_max)
			return (-1);
		counts[section]++;
		for (i = section + 1; i < ns_s_max; i++)
			if (counts[i])
				return (-3);
		rtype = rrecp->r_type;
		rclass = rrecp->r_class;
		rttl = rrecp->r_ttl;
		/* overload class and type */
		if (section == ns_s_pr) {
			rttl = 0;
			switch (rrecp->r_opcode) {
			case ns_r_yxdomain:
				rclass = ns_c_any;
				rtype = ns_t_any;
				rrecp->r_size = 0;
				break;
			case ns_r_nxdomain:
				rclass = ns_c_none;
				rtype = ns_t_any;
				rrecp->r_size = 0;
				break;
			case ns_r_nxrrset:
				rclass = ns_c_none;
				rrecp->r_size = 0;
				break;
			case ns_r_yxrrset:
				if (rrecp->r_size == 0)
					rclass = ns_c_any;
				break;
			default:
				fprintf(stderr,
					"res_mkupdate: incorrect opcode: %d\n",
					rrecp->r_opcode);
				fflush(stderr);
				return (-1);
			}
		} else if (section == ns_s_ud) {
			switch (rrecp->r_opcode) {
			case ns_uop_delete:
				rclass = rrecp->r_size == 0 ? ns_c_any : ns_c_none;
				break;
			case ns_uop_add:
				break;
			default:
				fprintf(stderr,
					"res_mkupdate: incorrect opcode: %d\n",
					rrecp->r_opcode);
				fflush(stderr);
				return (-1);
			}
		}

		/*
		 * XXX	appending default domain to owner name is omitted,
		 *	fqdn must be provided
		 */
		if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
				 lastdnptr)) < 0)
			return (-1);
		cp += n;
		ShrinkBuffer(n + 2*NS_INT16SZ);
		NS_PUT16(rtype, cp);
		NS_PUT16(rclass, cp);
		if (section == ns_s_zn) {
			if (numrrs != 1 || rrecp->r_type != ns_t_soa)
				return (-3);
			continue;
		}
		ShrinkBuffer(NS_INT32SZ + NS_INT16SZ);
		NS_PUT32(rttl, cp);
		sp2 = cp;  /* save pointer to length byte */
		cp += NS_INT16SZ;
		if (rrecp->r_size == 0) {
			if (section == ns_s_ud && rclass != ns_c_any)
				return (-1);
			else {
				NS_PUT16(0, sp2);
				continue;
			}
		}
		startp = rrecp->r_data;
		endp = startp + rrecp->r_size - 1;
		/* XXX this should be done centrally. */
		switch (rrecp->r_type) {
		case ns_t_a:
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			if (!inet_aton(buf2, &ina))
				return (-1);
			n1 = ntohl(ina.s_addr);
			ShrinkBuffer(NS_INT32SZ);
			NS_PUT32(n1, cp);
			break;
		case ns_t_cname:
		case ns_t_mb:
		case ns_t_mg:
		case ns_t_mr:
		case ns_t_ns:
		case ns_t_ptr:
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
			if (n < 0)
				return (-1);
			cp += n;
			ShrinkBuffer(n);
			break;
		case ns_t_minfo:
		case ns_t_soa:
		case ns_t_rp:
			for (i = 0; i < 2; i++) {
				if (!getword_str(buf2, sizeof buf2, &startp,
						 endp))
				return (-1);
				n = dn_comp(buf2, cp, buflen,
					    dnptrs, lastdnptr);
				if (n < 0)
					return (-1);
				cp += n;
				ShrinkBuffer(n);
			}
			if (rrecp->r_type == ns_t_soa) {
				ShrinkBuffer(5 * NS_INT32SZ);
				while (isspace(*startp) || !*startp)
					startp++;
				if (*startp == '(') {
					multiline = 1;
					startp++;
				} else
					multiline = 0;
				/* serial, refresh, retry, expire, minimum */
				for (i = 0; i < 5; i++) {
					soanum = getnum_str(&startp, endp);
					if (soanum < 0)
						return (-1);
					NS_PUT32(soanum, cp);
				}
				if (multiline) {
					while (isspace(*startp) || !*startp)
						startp++;
					if (*startp != ')')
						return (-1);
				}
			}
			break;
		case ns_t_mx:
		case ns_t_afsdb:
		case ns_t_rt:
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
			if (n < 0)
				return (-1);
			cp += n;
			ShrinkBuffer(n);
			break;
		case ns_t_srv:
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);

			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);

			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);

			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
			if (n < 0)
				return (-1);
			cp += n;
			ShrinkBuffer(n);
			break;
		case ns_t_px:
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			NS_PUT16(n, cp);
			ShrinkBuffer(NS_INT16SZ);
			for (i = 0; i < 2; i++) {
				if (!getword_str(buf2, sizeof buf2, &startp,
						 endp))
					return (-1);
				n = dn_comp(buf2, cp, buflen, dnptrs,
					    lastdnptr);
				if (n < 0)
					return (-1);
				cp += n;
				ShrinkBuffer(n);
			}
			break;
		case ns_t_wks: {
			char bm[MAXPORT/8];
			unsigned int maxbm = 0;

			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			if (!inet_aton(buf2, &ina))
				return (-1);
			n1 = ntohl(ina.s_addr);
			ShrinkBuffer(NS_INT32SZ);
			NS_PUT32(n1, cp);

			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			if ((i = res_protocolnumber(buf2)) < 0)
				return (-1);
			ShrinkBuffer(1);
			*cp++ = i & 0xff;
			 
			for (i = 0; i < MAXPORT/8 ; i++)
				bm[i] = 0;

			while (getword_str(buf2, sizeof buf2, &startp, endp)) {
				if ((n1 = res_servicenumber(buf2)) <= 0)
					return (-1);

				if (n1 < MAXPORT) {
					bm[n1/8] |= (0x80>>(n1%8));
					if (n1 > maxbm)
						maxbm = n1;
				} else
					return (-1);
			}
			maxbm = maxbm/8 + 1;
			ShrinkBuffer(maxbm);
			memcpy(cp, bm, maxbm);
			cp += maxbm;
			break;
		}
		case ns_t_hinfo:
			for (i = 0; i < 2; i++) {
				if ((n = getstr_str(buf2, sizeof buf2,
						&startp, endp)) < 0)
					return (-1);
				if (n > 255)
					return (-1);
				ShrinkBuffer(n+1);
				*cp++ = n;
				memcpy(cp, buf2, n);
				cp += n;
			}
			break;
		case ns_t_txt:
			while (1) {
				if ((n = getstr_str(buf2, sizeof buf2,
						&startp, endp)) < 0) {
					if (cp != (sp2 + NS_INT16SZ))
						break;
					return (-1);
				}
				if (n > 255)
					return (-1);
				ShrinkBuffer(n+1);
				*cp++ = n;
				memcpy(cp, buf2, n);
				cp += n;
			}
			break;
		case ns_t_x25:
			/* RFC 1183 */
			if ((n = getstr_str(buf2, sizeof buf2, &startp,
					 endp)) < 0)
				return (-1);
			if (n > 255)
				return (-1);
			ShrinkBuffer(n+1);
			*cp++ = n;
			memcpy(cp, buf2, n);
			cp += n;
			break;
		case ns_t_isdn:
			/* RFC 1183 */
			if ((n = getstr_str(buf2, sizeof buf2, &startp,
					 endp)) < 0)
				return (-1);
			if ((n > 255) || (n == 0))
				return (-1);
			ShrinkBuffer(n+1);
			*cp++ = n;
			memcpy(cp, buf2, n);
			cp += n;
			if ((n = getstr_str(buf2, sizeof buf2, &startp,
					 endp)) < 0)
				n = 0;
			if (n > 255)
				return (-1);
			ShrinkBuffer(n+1);
			*cp++ = n;
			memcpy(cp, buf2, n);
			cp += n;
			break;
		case ns_t_nsap:
			if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) {
				ShrinkBuffer(n);
				memcpy(cp, buf2, n);
				cp += n;
			} else {
				return (-1);
			}
			break;
		case ns_t_loc:
			if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) {
				ShrinkBuffer(n);
				memcpy(cp, buf2, n);
				cp += n;
			} else
				return (-1);
			break;
		case ns_t_sig:
		    {
			int sig_type, success, dateerror;
			u_int32_t exptime, timesigned;

			/* type */
			if ((n = getword_str(buf2, sizeof buf2,
					     &startp, endp)) < 0)
				return (-1);
			sig_type = sym_ston(__p_type_syms, buf2, &success);
			if (!success || sig_type == ns_t_any)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(sig_type, cp);
			/* alg */
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(1);
			*cp++ = n;
			/* labels */
			n = getnum_str(&startp, endp);
			if (n <= 0 || n > 255)
				return (-1);
			ShrinkBuffer(1);
			*cp++ = n;
			/* ottl  & expire */
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			exptime = ns_datetosecs(buf2, &dateerror);
			if (!dateerror) {
				ShrinkBuffer(NS_INT32SZ);
				NS_PUT32(rttl, cp);
			}
			else {
				char *ulendp;
				u_int32_t ottl;

				ottl = strtoul(buf2, &ulendp, 10);
				if (ulendp != NULL && *ulendp != '\0')
					return (-1);
				ShrinkBuffer(NS_INT32SZ);
				NS_PUT32(ottl, cp);
				if (!getword_str(buf2, sizeof buf2, &startp,
						 endp))
					return (-1);
				exptime = ns_datetosecs(buf2, &dateerror);
				if (dateerror)
					return (-1);
			}
			/* expire */
			ShrinkBuffer(NS_INT32SZ);
			NS_PUT32(exptime, cp);
			/* timesigned */
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			timesigned = ns_datetosecs(buf2, &dateerror);
			if (!dateerror) {
				ShrinkBuffer(NS_INT32SZ);
				NS_PUT32(timesigned, cp);
			}
			else
				return (-1);
			/* footprint */
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);
			/* signer name */
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
			if (n < 0)
				return (-1);
			cp += n;
			ShrinkBuffer(n);
			/* sig */
			if ((n = getword_str(buf2, sizeof buf2,
					     &startp, endp)) < 0)
				return (-1);
			siglen = b64_pton(buf2, buf3, sizeof(buf3));
			if (siglen < 0)
				return (-1);
			ShrinkBuffer(siglen);
			memcpy(cp, buf3, siglen);
			cp += siglen;
			break;
		    }
		case ns_t_key:
			/* flags */
			n = gethexnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);
			/* proto */
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(1);
			*cp++ = n;
			/* alg */
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(1);
			*cp++ = n;
			/* key */
			if ((n = getword_str(buf2, sizeof buf2,
					     &startp, endp)) < 0)
				return (-1);
			keylen = b64_pton(buf2, buf3, sizeof(buf3));
			if (keylen < 0)
				return (-1);
			ShrinkBuffer(keylen);
			memcpy(cp, buf3, keylen);
			cp += keylen;
			break;
		case ns_t_nxt:
		    {
			int success, nxt_type;
			u_char data[32];
			int maxtype;

			/* next name */
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
			if (n < 0)
				return (-1);
			cp += n;
			ShrinkBuffer(n);
			maxtype = 0;
			memset(data, 0, sizeof data);
			while (1) {
				if (!getword_str(buf2, sizeof buf2, &startp,
						 endp))
					break;
				nxt_type = sym_ston(__p_type_syms, buf2,
						    &success);
				if (!success || !ns_t_rr_p(nxt_type))
					return (-1);
				NS_NXT_BIT_SET(nxt_type, data);
				if (nxt_type > maxtype)
					maxtype = nxt_type;
			}
			n = maxtype/NS_NXT_BITS+1;
			ShrinkBuffer(n);
			memcpy(cp, data, n);
			cp += n;
			break;
		    }
		case ns_t_cert:
			/* type */
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);
			/* key tag */
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(NS_INT16SZ);
			NS_PUT16(n, cp);
			/* alg */
			n = getnum_str(&startp, endp);
			if (n < 0)
				return (-1);
			ShrinkBuffer(1);
			*cp++ = n;
			/* cert */
			if ((n = getword_str(buf2, sizeof buf2,
					     &startp, endp)) < 0)
				return (-1);
			certlen = b64_pton(buf2, buf3, sizeof(buf3));
			if (certlen < 0)
				return (-1);
			ShrinkBuffer(certlen);
			memcpy(cp, buf3, certlen);
			cp += certlen;
			break;
		case ns_t_aaaa:
			if (!getword_str(buf2, sizeof buf2, &startp, endp))
				return (-1);
			if (inet_pton(AF_INET6, buf2, &in6a) <= 0)
				return (-1);
			ShrinkBuffer(NS_IN6ADDRSZ);
			memcpy(cp, &in6a, NS_IN6ADDRSZ);
			cp += NS_IN6ADDRSZ;
			break;
		default:
			return (-1);
		} /*switch*/
Exemplo n.º 8
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 = msg + *msglen, *eob = msg + msgsize;
	u_char *lenp;
	u_char *name, *alg;
	int n;
	time_t timesigned;

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

	/* Name. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey)
		n = dn_comp(key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr);
	else
		n = dn_comp("", cp, eob - cp, NULL, NULL);
	if (n < 0)
		return (NS_TSIG_ERROR_NO_SPACE);
	name = cp;
	cp += n;

	/* Type, class, ttl, length (not filled in yet). */
	BOUNDS_CHECK(cp, NS_INT16SZ + NS_INT16SZ + NS_INT32SZ + NS_INT16SZ);
	NS_PUT16(ns_t_tsig, cp);
	NS_PUT16(ns_c_any, cp);
	NS_PUT32(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, NS_INT16SZ + NS_INT32SZ + NS_INT16SZ);
	NS_PUT16(0, cp);
	timesigned = time(NULL);
	if (error != ns_r_badtime)
		NS_PUT32(timesigned, cp);
	else
		NS_PUT32(in_timesigned, cp);
	NS_PUT16(NS_TSIG_FUDGE, cp);

	/* Compute the signature. */
	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		void *ctx;
		u_char buf[NS_MAXDNAME], *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, NS_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));
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the class and TTL. */
		cp2 = buf;
		NS_PUT16(ns_c_any, cp2);
		NS_PUT32(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));
		dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the time signed, fudge, error, and other data */
		cp2 = buf;
		NS_PUT16(0, cp2);	/* Top 16 bits of time */
		if (error != ns_r_badtime)
			NS_PUT32(timesigned, cp2);
		else
			NS_PUT32(in_timesigned, cp2);
		NS_PUT16(NS_TSIG_FUDGE, cp2);
		NS_PUT16(error, cp2);	/* Error */
		if (error != ns_r_badtime)
			NS_PUT16(0, cp2);	/* Other data length */
		else {
			NS_PUT16(NS_INT16SZ+NS_INT32SZ, cp2);	/* Other data length */
			NS_PUT16(0, cp2);	/* Top 16 bits of time */
			NS_PUT32(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, NS_INT16SZ + (*siglen));
	NS_PUT16(*siglen, cp);
	memcpy(cp, sig, *siglen);
	cp += (*siglen);

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

	/* Other data. */
	BOUNDS_CHECK(cp, NS_INT16SZ);
	if (error != ns_r_badtime)
		NS_PUT16(0, cp);	/* Other data length */
	else {
		NS_PUT16(NS_INT16SZ+NS_INT32SZ, cp);	/* Other data length */
		BOUNDS_CHECK(cp, NS_INT32SZ+NS_INT16SZ);
		NS_PUT16(0, cp);	/* Top 16 bits of time */
		NS_PUT32(timesigned, cp);
	}

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

	hp->arcount = htons(ntohs(hp->arcount) + 1);
	*msglen = (cp - msg);
	return (0);
}
Exemplo n.º 9
0
int
ns_sign_tcp2(u_char *msg, int *msglen, int msgsize, int error,
	     ns_tcp_tsig_state *state, int done,
	     u_char **dnptrs, u_char **lastdnptr)
{
	u_char *cp, *eob, *lenp;
	u_char buf[NS_MAXDNAME], *cp2;
	HEADER *hp = (HEADER *)msg;
	time_t timesigned;
	int n;

	if (msg == NULL || msglen == NULL || state == NULL)
		return (-1);

	state->counter++;
	if (state->counter == 0)
		return (ns_sign2(msg, msglen, msgsize, error, state->key,
				 state->sig, state->siglen,
				 state->sig, &state->siglen, 0,
				 dnptrs, lastdnptr));

	if (state->siglen > 0) {
		u_int16_t siglen_n = htons(state->siglen);
		dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx,
			      NULL, 0, NULL, 0);
		dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
			      (u_char *)&siglen_n, NS_INT16SZ, NULL, 0);
		dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
			      state->sig, state->siglen, NULL, 0);
		state->siglen = 0;
	}

	dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen,
		      NULL, 0);

	if (done == 0 && (state->counter % 100 != 0))
		return (0);

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

	/* Name. */
	n = dn_comp(state->key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr);
	if (n < 0)
		return (NS_TSIG_ERROR_NO_SPACE);
	cp += n;

	/* Type, class, ttl, length (not filled in yet). */
	BOUNDS_CHECK(cp, NS_INT16SZ + NS_INT16SZ + NS_INT32SZ + NS_INT16SZ);
	NS_PUT16(ns_t_tsig, cp);
	NS_PUT16(ns_c_any, cp);
	NS_PUT32(0, cp);		/* TTL */
	lenp = cp;
	cp += 2;

	/* Alg. */
	n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL);
	if (n < 0)
		return (NS_TSIG_ERROR_NO_SPACE);
	cp += n;
	
	/* Time. */
	BOUNDS_CHECK(cp, NS_INT16SZ + NS_INT32SZ + NS_INT16SZ);
	NS_PUT16(0, cp);
	timesigned = time(NULL);
	NS_PUT32(timesigned, cp);
	NS_PUT16(NS_TSIG_FUDGE, cp);

	/*
	 * Compute the signature.
	 */

	/* Digest the time signed and fudge. */
	cp2 = buf;
	NS_PUT16(0, cp2);	/* Top 16 bits of time */
	NS_PUT32(timesigned, cp2);
	NS_PUT16(NS_TSIG_FUDGE, cp2);

	dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
		      buf, cp2 - buf, NULL, 0);

	n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
			  state->sig, sizeof(state->sig));
	if (n < 0)
		return (-ns_r_badkey);
	state->siglen = n;

	/* Add the signature. */
	BOUNDS_CHECK(cp, NS_INT16SZ + state->siglen);
	NS_PUT16(state->siglen, cp);
	memcpy(cp, state->sig, state->siglen);
	cp += state->siglen;

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

	/* Other data. */
	BOUNDS_CHECK(cp, NS_INT16SZ);
	NS_PUT16(0, cp);

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

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