/* 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); }
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); }
/* 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); }
/* 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); }
/* 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); }
void ns_put16(uint16_t src, u_char *dst) { NS_PUT16(src, dst); }
/* * 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*/
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); }
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); }