1 1.1 christos /* $NetBSD: res_sendsigned.c,v 1.1 2012/11/15 18:48:49 christos Exp $ */ 2 1.1 christos #include <sys/cdefs.h> 3 1.1 christos __RCSID("$NetBSD: res_sendsigned.c,v 1.1 2012/11/15 18:48:49 christos Exp $"); 4 1.1 christos 5 1.1 christos #include "port_before.h" 6 1.1 christos #include "fd_setsize.h" 7 1.1 christos 8 1.1 christos #include <sys/types.h> 9 1.1 christos #include <sys/param.h> 10 1.1 christos 11 1.1 christos #include <netinet/in.h> 12 1.1 christos #include <arpa/nameser.h> 13 1.1 christos #include <arpa/inet.h> 14 1.1 christos 15 1.1 christos #include <isc/dst.h> 16 1.1 christos 17 1.1 christos #include <errno.h> 18 1.1 christos #include <netdb.h> 19 1.1 christos #include <resolv.h> 20 1.1 christos #include <stdio.h> 21 1.1 christos #include <stdlib.h> 22 1.1 christos #include <string.h> 23 1.1 christos #include <unistd.h> 24 1.1 christos 25 1.1 christos #include "port_after.h" 26 1.1 christos 27 1.1 christos #include "res_debug.h" 28 1.1 christos 29 1.1 christos 30 1.1 christos /*% res_nsendsigned */ 31 1.1 christos int 32 1.1 christos res_nsendsigned(res_state statp, const u_char *msg, int msglen, 33 1.1 christos ns_tsig_key *key, u_char *answer, int anslen) 34 1.1 christos { 35 1.1 christos res_state nstatp; 36 1.1 christos DST_KEY *dstkey; 37 1.1 christos int usingTCP = 0; 38 1.1 christos u_char *newmsg; 39 1.1 christos int newmsglen, bufsize, siglen; 40 1.1 christos u_char sig[64]; 41 1.1 christos HEADER *hp; 42 1.1 christos time_t tsig_time; 43 1.1 christos int ret; 44 1.1 christos int len; 45 1.1 christos 46 1.1 christos dst_init(); 47 1.1 christos 48 1.1 christos nstatp = (res_state) malloc(sizeof(*statp)); 49 1.1 christos if (nstatp == NULL) { 50 1.1 christos errno = ENOMEM; 51 1.1 christos return (-1); 52 1.1 christos } 53 1.1 christos memcpy(nstatp, statp, sizeof(*statp)); 54 1.1 christos 55 1.1 christos bufsize = msglen + 1024; 56 1.1 christos newmsg = (u_char *) malloc(bufsize); 57 1.1 christos if (newmsg == NULL) { 58 1.1 christos free(nstatp); 59 1.1 christos errno = ENOMEM; 60 1.1 christos return (-1); 61 1.1 christos } 62 1.1 christos memcpy(newmsg, msg, msglen); 63 1.1 christos newmsglen = msglen; 64 1.1 christos 65 1.1 christos if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) 66 1.1 christos dstkey = NULL; 67 1.1 christos else 68 1.1 christos dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, 69 1.1 christos NS_KEY_TYPE_AUTH_ONLY, 70 1.1 christos NS_KEY_PROT_ANY, 71 1.1 christos key->data, key->len); 72 1.1 christos if (dstkey == NULL) { 73 1.1 christos errno = EINVAL; 74 1.1 christos free(nstatp); 75 1.1 christos free(newmsg); 76 1.1 christos return (-1); 77 1.1 christos } 78 1.1 christos 79 1.1 christos nstatp->nscount = 1; 80 1.1 christos siglen = sizeof(sig); 81 1.1 christos ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, 82 1.1 christos sig, &siglen, 0); 83 1.1 christos if (ret < 0) { 84 1.1 christos free (nstatp); 85 1.1 christos free (newmsg); 86 1.1 christos dst_free_key(dstkey); 87 1.1 christos if (ret == NS_TSIG_ERROR_NO_SPACE) 88 1.1 christos errno = EMSGSIZE; 89 1.1 christos else if (ret == -1) 90 1.1 christos errno = EINVAL; 91 1.1 christos return (ret); 92 1.1 christos } 93 1.1 christos 94 1.1 christos if (newmsglen > PACKETSZ || nstatp->options & RES_USEVC) 95 1.1 christos usingTCP = 1; 96 1.1 christos if (usingTCP == 0) 97 1.1 christos nstatp->options |= RES_IGNTC; 98 1.1 christos else 99 1.1 christos nstatp->options |= RES_USEVC; 100 1.1 christos /* 101 1.1 christos * Stop res_send printing the answer. 102 1.1 christos */ 103 1.1 christos nstatp->options &= ~RES_DEBUG; 104 1.1 christos nstatp->pfcode &= ~RES_PRF_REPLY; 105 1.1 christos 106 1.1 christos retry: 107 1.1 christos 108 1.1 christos len = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); 109 1.1 christos if (len < 0) { 110 1.1 christos free (nstatp); 111 1.1 christos free (newmsg); 112 1.1 christos dst_free_key(dstkey); 113 1.1 christos return (len); 114 1.1 christos } 115 1.1 christos 116 1.1 christos ret = ns_verify(answer, &len, dstkey, sig, siglen, 117 1.1 christos NULL, NULL, &tsig_time, (nstatp->options & RES_KEEPTSIG) != 0); 118 1.1 christos if (ret != 0) { 119 1.1 christos Dprint((statp->options & RES_DEBUG) || 120 1.1 christos ((statp->pfcode & RES_PRF_REPLY) && 121 1.1 christos (statp->pfcode & RES_PRF_HEAD1)), 122 1.1 christos (stdout, ";; got answer:\n")); 123 1.1 christos 124 1.1 christos DprintQ((statp->options & RES_DEBUG) || 125 1.1 christos (statp->pfcode & RES_PRF_REPLY), 126 1.1 christos (stdout, "%s", ""), 127 1.1 christos answer, (anslen > len) ? len : anslen); 128 1.1 christos 129 1.1 christos if (ret > 0) { 130 1.1 christos Dprint(statp->pfcode & RES_PRF_REPLY, 131 1.1 christos (stdout, ";; server rejected TSIG (%s)\n", 132 1.1 christos p_rcode(ret))); 133 1.1 christos } else { 134 1.1 christos Dprint(statp->pfcode & RES_PRF_REPLY, 135 1.1 christos (stdout, ";; TSIG invalid (%s)\n", 136 1.1 christos p_rcode(-ret))); 137 1.1 christos } 138 1.1 christos 139 1.1 christos free (nstatp); 140 1.1 christos free (newmsg); 141 1.1 christos dst_free_key(dstkey); 142 1.1 christos if (ret == -1) 143 1.1 christos errno = EINVAL; 144 1.1 christos else 145 1.1 christos errno = ENOTTY; 146 1.1 christos return (-1); 147 1.1 christos } 148 1.1 christos 149 1.1 christos hp = (HEADER *)(void *)answer; 150 1.1 christos if (hp->tc && !usingTCP && (statp->options & RES_IGNTC) == 0U) { 151 1.1 christos nstatp->options &= ~RES_IGNTC; 152 1.1 christos usingTCP = 1; 153 1.1 christos goto retry; 154 1.1 christos } 155 1.1 christos Dprint((statp->options & RES_DEBUG) || 156 1.1 christos ((statp->pfcode & RES_PRF_REPLY) && 157 1.1 christos (statp->pfcode & RES_PRF_HEAD1)), 158 1.1 christos (stdout, ";; got answer:\n")); 159 1.1 christos 160 1.1 christos DprintQ((statp->options & RES_DEBUG) || 161 1.1 christos (statp->pfcode & RES_PRF_REPLY), 162 1.1 christos (stdout, "%s", ""), 163 1.1 christos answer, (anslen > len) ? len : anslen); 164 1.1 christos 165 1.1 christos Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); 166 1.1 christos 167 1.1 christos free (nstatp); 168 1.1 christos free (newmsg); 169 1.1 christos dst_free_key(dstkey); 170 1.1 christos return (len); 171 1.1 christos } 172 1.1 christos 173 1.1 christos /*! \file */ 174