DST_KEY * dst_read_key(const char *in_keyname, const u_int16_t in_id, const int in_alg, const int type) { char keyname[PATH_MAX]; DST_KEY *dg_key = NULL, *pubkey = NULL; if (!dst_check_algorithm(in_alg)) { /*%< make sure alg is available */ EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", in_alg)); return (NULL); } if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) return (NULL); if (in_keyname == NULL) { EREPORT(("dst_read_private_key(): Null key name passed in\n")); return (NULL); } else if (strlen(in_keyname) >= sizeof(keyname)) { EREPORT(("dst_read_private_key(): keyname too big\n")); return (NULL); } else strcpy(keyname, in_keyname); /* before I read in the public key, check if it is allowed to sign */ if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) return (NULL); if (type == DST_PUBLIC) return pubkey; if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, pubkey->dk_flags, pubkey->dk_proto, 0))) return (dg_key); /* Fill in private key and some fields in the general key structure */ if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, pubkey->dk_alg) == 0) dg_key = dst_free_key(dg_key); (void)dst_free_key(pubkey); return (dg_key); }
/* res_nsendsigned */ int res_nsendsigned(res_state statp, const u_char *msg, int msglen, ns_tsig_key *key, u_char *answer, int anslen) { res_state nstatp; DST_KEY *dstkey; int usingTCP = 0; u_char *newmsg; int newmsglen, bufsize, siglen; u_char sig[64]; HEADER *hp; time_t tsig_time; int ret; dst_init(); nstatp = (res_state) malloc(sizeof(*statp)); if (nstatp == NULL) { errno = ENOMEM; return (-1); } memcpy(nstatp, statp, sizeof(*statp)); bufsize = msglen + 1024; newmsg = (u_char *) malloc(bufsize); if (newmsg == NULL) { errno = ENOMEM; return (-1); } memcpy(newmsg, msg, msglen); newmsglen = msglen; if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) dstkey = NULL; else dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, NS_KEY_TYPE_AUTH_ONLY, NS_KEY_PROT_ANY, key->data, key->len); if (dstkey == NULL) { errno = EINVAL; free(nstatp); free(newmsg); return (-1); } nstatp->nscount = 1; siglen = sizeof(sig); ret = ns_sign(newmsg, &newmsglen, bufsize, ns_r_noerror, dstkey, NULL, 0, sig, &siglen, 0); if (ret < 0) { free (nstatp); free (newmsg); dst_free_key(dstkey); if (ret == NS_TSIG_ERROR_NO_SPACE) errno = EMSGSIZE; else if (ret == -1) errno = EINVAL; return (ret); } if (newmsglen > NS_PACKETSZ || (nstatp->options & RES_IGNTC)) usingTCP = 1; if (usingTCP == 0) nstatp->options |= RES_IGNTC; else nstatp->options |= RES_USEVC; retry: ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); if (ret < 0) { free (nstatp); free (newmsg); dst_free_key(dstkey); return (ret); } anslen = ret; ret = ns_verify(answer, &anslen, dstkey, sig, siglen, NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); if (ret != 0) { Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret))); free (nstatp); free (newmsg); dst_free_key(dstkey); if (ret == -1) errno = EINVAL; else errno = ENOTTY; return (-1); } Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); hp = (HEADER *) answer; if (hp->tc && usingTCP == 0) { nstatp->options &= ~RES_IGNTC; usingTCP = 1; goto retry; } free (nstatp); free (newmsg); dst_free_key(dstkey); return (anslen); }
/*% res_nsendsigned */ int res_nsendsigned(res_state statp, const u_char *msg, int msglen, ns_tsig_key *key, u_char *answer, int anslen) { res_state nstatp; DST_KEY *dstkey; int usingTCP = 0; u_char *newmsg; int newmsglen, bufsize, siglen; u_char sig[64]; HEADER *hp; time_t tsig_time; int ret; int len; dst_init(); nstatp = (res_state) malloc(sizeof(*statp)); if (nstatp == NULL) { errno = ENOMEM; return (-1); } memcpy(nstatp, statp, sizeof(*statp)); bufsize = msglen + 1024; newmsg = (u_char *) malloc(bufsize); if (newmsg == NULL) { free(nstatp); errno = ENOMEM; return (-1); } memcpy(newmsg, msg, msglen); newmsglen = msglen; if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) dstkey = NULL; else dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, NS_KEY_TYPE_AUTH_ONLY, NS_KEY_PROT_ANY, key->data, key->len); if (dstkey == NULL) { errno = EINVAL; free(nstatp); free(newmsg); return (-1); } nstatp->nscount = 1; siglen = sizeof(sig); ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, sig, &siglen, 0); if (ret < 0) { free (nstatp); free (newmsg); dst_free_key(dstkey); if (ret == NS_TSIG_ERROR_NO_SPACE) errno = EMSGSIZE; else if (ret == -1) errno = EINVAL; return (ret); } if (newmsglen > PACKETSZ || nstatp->options & RES_USEVC) usingTCP = 1; if (usingTCP == 0) nstatp->options |= RES_IGNTC; else nstatp->options |= RES_USEVC; /* * Stop res_send printing the answer. */ nstatp->options &= ~RES_DEBUG; nstatp->pfcode &= ~RES_PRF_REPLY; retry: len = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); if (len < 0) { free (nstatp); free (newmsg); dst_free_key(dstkey); return (len); } ret = ns_verify(answer, &len, dstkey, sig, siglen, NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); if (ret != 0) { Dprint((statp->options & RES_DEBUG) || ((statp->pfcode & RES_PRF_REPLY) && (statp->pfcode & RES_PRF_HEAD1)), (stdout, ";; got answer:\n")); DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), (stdout, "%s", ""), answer, (anslen > len) ? len : anslen); if (ret > 0) { Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; server rejected TSIG (%s)\n", p_rcode(ret))); } else { Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG invalid (%s)\n", p_rcode(-ret))); } free (nstatp); free (newmsg); dst_free_key(dstkey); if (ret == -1) errno = EINVAL; else errno = ENOTTY; return (-1); } hp = (HEADER *) answer; if (hp->tc && !usingTCP && (statp->options & RES_IGNTC) == 0U) { nstatp->options &= ~RES_IGNTC; usingTCP = 1; goto retry; } Dprint((statp->options & RES_DEBUG) || ((statp->pfcode & RES_PRF_REPLY) && (statp->pfcode & RES_PRF_HEAD1)), (stdout, ";; got answer:\n")); DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), (stdout, "%s", ""), answer, (anslen > len) ? len : anslen); Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); free (nstatp); free (newmsg); dst_free_key(dstkey); return (len); }