1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 * 5 * No ISC copyright for this file. 6 */ 7 8 #pragma ident "%Z%%M% %I% %E% SMI" 9 10 #include "port_before.h" 11 #include "fd_setsize.h" 12 13 #include <sys/types.h> 14 #include <sys/param.h> 15 16 #include <netinet/in.h> 17 #include <arpa/nameser.h> 18 #include <arpa/inet.h> 19 20 #include <isc/dst.h> 21 22 #include <errno.h> 23 #include <netdb.h> 24 #include <resolv.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 #include "port_after.h" 31 32 #define DEBUG 33 #include "res_debug.h" 34 35 36 /* res_nsendsigned */ 37 int 38 res_nsendsigned(res_state statp, const u_char *msg, int msglen, 39 ns_tsig_key *key, u_char *answer, int anslen) 40 { 41 res_state nstatp; 42 DST_KEY *dstkey; 43 int usingTCP = 0; 44 u_char *newmsg; 45 int newmsglen, bufsize, siglen; 46 u_char sig[64]; 47 HEADER *hp; 48 time_t tsig_time; 49 int ret; 50 51 dst_init(); 52 53 nstatp = (res_state) malloc(sizeof(*statp)); 54 if (nstatp == NULL) { 55 errno = ENOMEM; 56 return (-1); 57 } 58 memcpy(nstatp, statp, sizeof(*statp)); 59 60 bufsize = msglen + 1024; 61 newmsg = (u_char *) malloc(bufsize); 62 if (newmsg == NULL) { 63 errno = ENOMEM; 64 return (-1); 65 } 66 memcpy(newmsg, msg, msglen); 67 newmsglen = msglen; 68 69 if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) 70 dstkey = NULL; 71 else 72 dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, 73 NS_KEY_TYPE_AUTH_ONLY, 74 NS_KEY_PROT_ANY, 75 key->data, key->len); 76 if (dstkey == NULL) { 77 errno = EINVAL; 78 free(nstatp); 79 free(newmsg); 80 return (-1); 81 } 82 83 nstatp->nscount = 1; 84 siglen = sizeof(sig); 85 ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, 86 sig, &siglen, 0); 87 if (ret < 0) { 88 free (nstatp); 89 free (newmsg); 90 dst_free_key(dstkey); 91 if (ret == NS_TSIG_ERROR_NO_SPACE) 92 errno = EMSGSIZE; 93 else if (ret == -1) 94 errno = EINVAL; 95 return (ret); 96 } 97 98 if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC)) 99 usingTCP = 1; 100 if (usingTCP == 0) 101 nstatp->options |= RES_IGNTC; 102 else 103 nstatp->options |= RES_USEVC; 104 105 retry: 106 107 ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); 108 if (ret < 0) { 109 free (nstatp); 110 free (newmsg); 111 dst_free_key(dstkey); 112 return (ret); 113 } 114 115 anslen = ret; 116 ret = ns_verify(answer, &anslen, dstkey, sig, siglen, 117 NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); 118 if (ret != 0) { 119 #ifdef ORIGINAL_ISC_CODE 120 Dprint(nstatp->pfcode & RES_PRF_REPLY, 121 (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret))); 122 #else 123 Dprint(nstatp->pfcode & RES_PRF_REPLY, 124 (stdout, ";; TSIG invalid (%s)\n", p_rcode(-ret))); 125 #endif 126 free (nstatp); 127 free (newmsg); 128 dst_free_key(dstkey); 129 if (ret == -1) 130 errno = EINVAL; 131 else 132 errno = ENOTTY; 133 return (-1); 134 } 135 Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); 136 137 hp = (HEADER *) answer; 138 if (hp->tc && usingTCP == 0) { 139 nstatp->options &= ~RES_IGNTC; 140 usingTCP = 1; 141 goto retry; 142 } 143 144 free (nstatp); 145 free (newmsg); 146 dst_free_key(dstkey); 147 return (anslen); 148 } 149