10Sstevel@tonic-gate #include "port_before.h"
20Sstevel@tonic-gate #include "fd_setsize.h"
30Sstevel@tonic-gate
40Sstevel@tonic-gate #include <sys/types.h>
50Sstevel@tonic-gate #include <sys/param.h>
60Sstevel@tonic-gate
70Sstevel@tonic-gate #include <netinet/in.h>
80Sstevel@tonic-gate #include <arpa/nameser.h>
90Sstevel@tonic-gate #include <arpa/inet.h>
100Sstevel@tonic-gate
110Sstevel@tonic-gate #include <isc/dst.h>
120Sstevel@tonic-gate
130Sstevel@tonic-gate #include <errno.h>
140Sstevel@tonic-gate #include <netdb.h>
150Sstevel@tonic-gate #include <resolv.h>
160Sstevel@tonic-gate #include <stdio.h>
170Sstevel@tonic-gate #include <stdlib.h>
180Sstevel@tonic-gate #include <string.h>
190Sstevel@tonic-gate #include <unistd.h>
200Sstevel@tonic-gate
210Sstevel@tonic-gate #include "port_after.h"
220Sstevel@tonic-gate
230Sstevel@tonic-gate #define DEBUG
240Sstevel@tonic-gate #include "res_debug.h"
250Sstevel@tonic-gate
260Sstevel@tonic-gate
27*11038SRao.Shoaib@Sun.COM /*% res_nsendsigned */
280Sstevel@tonic-gate int
res_nsendsigned(res_state statp,const u_char * msg,int msglen,ns_tsig_key * key,u_char * answer,int anslen)290Sstevel@tonic-gate res_nsendsigned(res_state statp, const u_char *msg, int msglen,
300Sstevel@tonic-gate ns_tsig_key *key, u_char *answer, int anslen)
310Sstevel@tonic-gate {
320Sstevel@tonic-gate res_state nstatp;
330Sstevel@tonic-gate DST_KEY *dstkey;
340Sstevel@tonic-gate int usingTCP = 0;
350Sstevel@tonic-gate u_char *newmsg;
360Sstevel@tonic-gate int newmsglen, bufsize, siglen;
370Sstevel@tonic-gate u_char sig[64];
380Sstevel@tonic-gate HEADER *hp;
390Sstevel@tonic-gate time_t tsig_time;
400Sstevel@tonic-gate int ret;
41*11038SRao.Shoaib@Sun.COM int len;
420Sstevel@tonic-gate
430Sstevel@tonic-gate dst_init();
440Sstevel@tonic-gate
450Sstevel@tonic-gate nstatp = (res_state) malloc(sizeof(*statp));
460Sstevel@tonic-gate if (nstatp == NULL) {
470Sstevel@tonic-gate errno = ENOMEM;
480Sstevel@tonic-gate return (-1);
490Sstevel@tonic-gate }
500Sstevel@tonic-gate memcpy(nstatp, statp, sizeof(*statp));
510Sstevel@tonic-gate
520Sstevel@tonic-gate bufsize = msglen + 1024;
530Sstevel@tonic-gate newmsg = (u_char *) malloc(bufsize);
540Sstevel@tonic-gate if (newmsg == NULL) {
55*11038SRao.Shoaib@Sun.COM free(nstatp);
560Sstevel@tonic-gate errno = ENOMEM;
570Sstevel@tonic-gate return (-1);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate memcpy(newmsg, msg, msglen);
600Sstevel@tonic-gate newmsglen = msglen;
610Sstevel@tonic-gate
620Sstevel@tonic-gate if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1)
630Sstevel@tonic-gate dstkey = NULL;
640Sstevel@tonic-gate else
650Sstevel@tonic-gate dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5,
660Sstevel@tonic-gate NS_KEY_TYPE_AUTH_ONLY,
670Sstevel@tonic-gate NS_KEY_PROT_ANY,
680Sstevel@tonic-gate key->data, key->len);
690Sstevel@tonic-gate if (dstkey == NULL) {
700Sstevel@tonic-gate errno = EINVAL;
710Sstevel@tonic-gate free(nstatp);
720Sstevel@tonic-gate free(newmsg);
730Sstevel@tonic-gate return (-1);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate
760Sstevel@tonic-gate nstatp->nscount = 1;
770Sstevel@tonic-gate siglen = sizeof(sig);
780Sstevel@tonic-gate ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0,
790Sstevel@tonic-gate sig, &siglen, 0);
800Sstevel@tonic-gate if (ret < 0) {
810Sstevel@tonic-gate free (nstatp);
820Sstevel@tonic-gate free (newmsg);
830Sstevel@tonic-gate dst_free_key(dstkey);
840Sstevel@tonic-gate if (ret == NS_TSIG_ERROR_NO_SPACE)
850Sstevel@tonic-gate errno = EMSGSIZE;
860Sstevel@tonic-gate else if (ret == -1)
870Sstevel@tonic-gate errno = EINVAL;
880Sstevel@tonic-gate return (ret);
890Sstevel@tonic-gate }
900Sstevel@tonic-gate
91*11038SRao.Shoaib@Sun.COM if (newmsglen > PACKETSZ || nstatp->options & RES_USEVC)
920Sstevel@tonic-gate usingTCP = 1;
930Sstevel@tonic-gate if (usingTCP == 0)
940Sstevel@tonic-gate nstatp->options |= RES_IGNTC;
950Sstevel@tonic-gate else
960Sstevel@tonic-gate nstatp->options |= RES_USEVC;
97*11038SRao.Shoaib@Sun.COM /*
98*11038SRao.Shoaib@Sun.COM * Stop res_send printing the answer.
99*11038SRao.Shoaib@Sun.COM */
100*11038SRao.Shoaib@Sun.COM nstatp->options &= ~RES_DEBUG;
101*11038SRao.Shoaib@Sun.COM nstatp->pfcode &= ~RES_PRF_REPLY;
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate retry:
1040Sstevel@tonic-gate
105*11038SRao.Shoaib@Sun.COM len = res_nsend(nstatp, newmsg, newmsglen, answer, anslen);
106*11038SRao.Shoaib@Sun.COM if (len < 0) {
1070Sstevel@tonic-gate free (nstatp);
1080Sstevel@tonic-gate free (newmsg);
1090Sstevel@tonic-gate dst_free_key(dstkey);
110*11038SRao.Shoaib@Sun.COM return (len);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate
113*11038SRao.Shoaib@Sun.COM ret = ns_verify(answer, &len, dstkey, sig, siglen,
1140Sstevel@tonic-gate NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG);
1150Sstevel@tonic-gate if (ret != 0) {
116*11038SRao.Shoaib@Sun.COM Dprint((statp->options & RES_DEBUG) ||
117*11038SRao.Shoaib@Sun.COM ((statp->pfcode & RES_PRF_REPLY) &&
118*11038SRao.Shoaib@Sun.COM (statp->pfcode & RES_PRF_HEAD1)),
119*11038SRao.Shoaib@Sun.COM (stdout, ";; got answer:\n"));
120*11038SRao.Shoaib@Sun.COM
121*11038SRao.Shoaib@Sun.COM DprintQ((statp->options & RES_DEBUG) ||
122*11038SRao.Shoaib@Sun.COM (statp->pfcode & RES_PRF_REPLY),
123*11038SRao.Shoaib@Sun.COM (stdout, "%s", ""),
124*11038SRao.Shoaib@Sun.COM answer, (anslen > len) ? len : anslen);
125*11038SRao.Shoaib@Sun.COM
126*11038SRao.Shoaib@Sun.COM if (ret > 0) {
127*11038SRao.Shoaib@Sun.COM Dprint(statp->pfcode & RES_PRF_REPLY,
128*11038SRao.Shoaib@Sun.COM (stdout, ";; server rejected TSIG (%s)\n",
129*11038SRao.Shoaib@Sun.COM p_rcode(ret)));
130*11038SRao.Shoaib@Sun.COM } else {
131*11038SRao.Shoaib@Sun.COM Dprint(statp->pfcode & RES_PRF_REPLY,
132*11038SRao.Shoaib@Sun.COM (stdout, ";; TSIG invalid (%s)\n",
133*11038SRao.Shoaib@Sun.COM p_rcode(-ret)));
134*11038SRao.Shoaib@Sun.COM }
135*11038SRao.Shoaib@Sun.COM
1360Sstevel@tonic-gate free (nstatp);
1370Sstevel@tonic-gate free (newmsg);
1380Sstevel@tonic-gate dst_free_key(dstkey);
1390Sstevel@tonic-gate if (ret == -1)
1400Sstevel@tonic-gate errno = EINVAL;
1410Sstevel@tonic-gate else
1420Sstevel@tonic-gate errno = ENOTTY;
1430Sstevel@tonic-gate return (-1);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate hp = (HEADER *) answer;
147*11038SRao.Shoaib@Sun.COM if (hp->tc && !usingTCP && (statp->options & RES_IGNTC) == 0U) {
1480Sstevel@tonic-gate nstatp->options &= ~RES_IGNTC;
1490Sstevel@tonic-gate usingTCP = 1;
1500Sstevel@tonic-gate goto retry;
1510Sstevel@tonic-gate }
152*11038SRao.Shoaib@Sun.COM Dprint((statp->options & RES_DEBUG) ||
153*11038SRao.Shoaib@Sun.COM ((statp->pfcode & RES_PRF_REPLY) &&
154*11038SRao.Shoaib@Sun.COM (statp->pfcode & RES_PRF_HEAD1)),
155*11038SRao.Shoaib@Sun.COM (stdout, ";; got answer:\n"));
156*11038SRao.Shoaib@Sun.COM
157*11038SRao.Shoaib@Sun.COM DprintQ((statp->options & RES_DEBUG) ||
158*11038SRao.Shoaib@Sun.COM (statp->pfcode & RES_PRF_REPLY),
159*11038SRao.Shoaib@Sun.COM (stdout, "%s", ""),
160*11038SRao.Shoaib@Sun.COM answer, (anslen > len) ? len : anslen);
161*11038SRao.Shoaib@Sun.COM
162*11038SRao.Shoaib@Sun.COM Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n"));
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate free (nstatp);
1650Sstevel@tonic-gate free (newmsg);
1660Sstevel@tonic-gate dst_free_key(dstkey);
167*11038SRao.Shoaib@Sun.COM return (len);
1680Sstevel@tonic-gate }
169*11038SRao.Shoaib@Sun.COM
170*11038SRao.Shoaib@Sun.COM /*! \file */
171