17c478bd9Sstevel@tonic-gate #include "port_before.h"
27c478bd9Sstevel@tonic-gate #include "fd_setsize.h"
37c478bd9Sstevel@tonic-gate
47c478bd9Sstevel@tonic-gate #include <sys/types.h>
57c478bd9Sstevel@tonic-gate #include <sys/param.h>
67c478bd9Sstevel@tonic-gate
77c478bd9Sstevel@tonic-gate #include <netinet/in.h>
87c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
97c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
107c478bd9Sstevel@tonic-gate
117c478bd9Sstevel@tonic-gate #include <isc/dst.h>
127c478bd9Sstevel@tonic-gate
137c478bd9Sstevel@tonic-gate #include <errno.h>
147c478bd9Sstevel@tonic-gate #include <netdb.h>
157c478bd9Sstevel@tonic-gate #include <resolv.h>
167c478bd9Sstevel@tonic-gate #include <stdio.h>
177c478bd9Sstevel@tonic-gate #include <stdlib.h>
187c478bd9Sstevel@tonic-gate #include <string.h>
197c478bd9Sstevel@tonic-gate #include <unistd.h>
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate #include "port_after.h"
227c478bd9Sstevel@tonic-gate
237c478bd9Sstevel@tonic-gate #define DEBUG
247c478bd9Sstevel@tonic-gate #include "res_debug.h"
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate
27*9525b14bSRao Shoaib /*% res_nsendsigned */
287c478bd9Sstevel@tonic-gate int
res_nsendsigned(res_state statp,const u_char * msg,int msglen,ns_tsig_key * key,u_char * answer,int anslen)297c478bd9Sstevel@tonic-gate res_nsendsigned(res_state statp, const u_char *msg, int msglen,
307c478bd9Sstevel@tonic-gate ns_tsig_key *key, u_char *answer, int anslen)
317c478bd9Sstevel@tonic-gate {
327c478bd9Sstevel@tonic-gate res_state nstatp;
337c478bd9Sstevel@tonic-gate DST_KEY *dstkey;
347c478bd9Sstevel@tonic-gate int usingTCP = 0;
357c478bd9Sstevel@tonic-gate u_char *newmsg;
367c478bd9Sstevel@tonic-gate int newmsglen, bufsize, siglen;
377c478bd9Sstevel@tonic-gate u_char sig[64];
387c478bd9Sstevel@tonic-gate HEADER *hp;
397c478bd9Sstevel@tonic-gate time_t tsig_time;
407c478bd9Sstevel@tonic-gate int ret;
41*9525b14bSRao Shoaib int len;
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate dst_init();
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate nstatp = (res_state) malloc(sizeof(*statp));
467c478bd9Sstevel@tonic-gate if (nstatp == NULL) {
477c478bd9Sstevel@tonic-gate errno = ENOMEM;
487c478bd9Sstevel@tonic-gate return (-1);
497c478bd9Sstevel@tonic-gate }
507c478bd9Sstevel@tonic-gate memcpy(nstatp, statp, sizeof(*statp));
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate bufsize = msglen + 1024;
537c478bd9Sstevel@tonic-gate newmsg = (u_char *) malloc(bufsize);
547c478bd9Sstevel@tonic-gate if (newmsg == NULL) {
55*9525b14bSRao Shoaib free(nstatp);
567c478bd9Sstevel@tonic-gate errno = ENOMEM;
577c478bd9Sstevel@tonic-gate return (-1);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate memcpy(newmsg, msg, msglen);
607c478bd9Sstevel@tonic-gate newmsglen = msglen;
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1)
637c478bd9Sstevel@tonic-gate dstkey = NULL;
647c478bd9Sstevel@tonic-gate else
657c478bd9Sstevel@tonic-gate dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5,
667c478bd9Sstevel@tonic-gate NS_KEY_TYPE_AUTH_ONLY,
677c478bd9Sstevel@tonic-gate NS_KEY_PROT_ANY,
687c478bd9Sstevel@tonic-gate key->data, key->len);
697c478bd9Sstevel@tonic-gate if (dstkey == NULL) {
707c478bd9Sstevel@tonic-gate errno = EINVAL;
717c478bd9Sstevel@tonic-gate free(nstatp);
727c478bd9Sstevel@tonic-gate free(newmsg);
737c478bd9Sstevel@tonic-gate return (-1);
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate nstatp->nscount = 1;
777c478bd9Sstevel@tonic-gate siglen = sizeof(sig);
787c478bd9Sstevel@tonic-gate ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0,
797c478bd9Sstevel@tonic-gate sig, &siglen, 0);
807c478bd9Sstevel@tonic-gate if (ret < 0) {
817c478bd9Sstevel@tonic-gate free (nstatp);
827c478bd9Sstevel@tonic-gate free (newmsg);
837c478bd9Sstevel@tonic-gate dst_free_key(dstkey);
847c478bd9Sstevel@tonic-gate if (ret == NS_TSIG_ERROR_NO_SPACE)
857c478bd9Sstevel@tonic-gate errno = EMSGSIZE;
867c478bd9Sstevel@tonic-gate else if (ret == -1)
877c478bd9Sstevel@tonic-gate errno = EINVAL;
887c478bd9Sstevel@tonic-gate return (ret);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate
91*9525b14bSRao Shoaib if (newmsglen > PACKETSZ || nstatp->options & RES_USEVC)
927c478bd9Sstevel@tonic-gate usingTCP = 1;
937c478bd9Sstevel@tonic-gate if (usingTCP == 0)
947c478bd9Sstevel@tonic-gate nstatp->options |= RES_IGNTC;
957c478bd9Sstevel@tonic-gate else
967c478bd9Sstevel@tonic-gate nstatp->options |= RES_USEVC;
97*9525b14bSRao Shoaib /*
98*9525b14bSRao Shoaib * Stop res_send printing the answer.
99*9525b14bSRao Shoaib */
100*9525b14bSRao Shoaib nstatp->options &= ~RES_DEBUG;
101*9525b14bSRao Shoaib nstatp->pfcode &= ~RES_PRF_REPLY;
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate retry:
1047c478bd9Sstevel@tonic-gate
105*9525b14bSRao Shoaib len = res_nsend(nstatp, newmsg, newmsglen, answer, anslen);
106*9525b14bSRao Shoaib if (len < 0) {
1077c478bd9Sstevel@tonic-gate free (nstatp);
1087c478bd9Sstevel@tonic-gate free (newmsg);
1097c478bd9Sstevel@tonic-gate dst_free_key(dstkey);
110*9525b14bSRao Shoaib return (len);
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate
113*9525b14bSRao Shoaib ret = ns_verify(answer, &len, dstkey, sig, siglen,
1147c478bd9Sstevel@tonic-gate NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG);
1157c478bd9Sstevel@tonic-gate if (ret != 0) {
116*9525b14bSRao Shoaib Dprint((statp->options & RES_DEBUG) ||
117*9525b14bSRao Shoaib ((statp->pfcode & RES_PRF_REPLY) &&
118*9525b14bSRao Shoaib (statp->pfcode & RES_PRF_HEAD1)),
119*9525b14bSRao Shoaib (stdout, ";; got answer:\n"));
120*9525b14bSRao Shoaib
121*9525b14bSRao Shoaib DprintQ((statp->options & RES_DEBUG) ||
122*9525b14bSRao Shoaib (statp->pfcode & RES_PRF_REPLY),
123*9525b14bSRao Shoaib (stdout, "%s", ""),
124*9525b14bSRao Shoaib answer, (anslen > len) ? len : anslen);
125*9525b14bSRao Shoaib
126*9525b14bSRao Shoaib if (ret > 0) {
127*9525b14bSRao Shoaib Dprint(statp->pfcode & RES_PRF_REPLY,
128*9525b14bSRao Shoaib (stdout, ";; server rejected TSIG (%s)\n",
129*9525b14bSRao Shoaib p_rcode(ret)));
130*9525b14bSRao Shoaib } else {
131*9525b14bSRao Shoaib Dprint(statp->pfcode & RES_PRF_REPLY,
132*9525b14bSRao Shoaib (stdout, ";; TSIG invalid (%s)\n",
133*9525b14bSRao Shoaib p_rcode(-ret)));
134*9525b14bSRao Shoaib }
135*9525b14bSRao Shoaib
1367c478bd9Sstevel@tonic-gate free (nstatp);
1377c478bd9Sstevel@tonic-gate free (newmsg);
1387c478bd9Sstevel@tonic-gate dst_free_key(dstkey);
1397c478bd9Sstevel@tonic-gate if (ret == -1)
1407c478bd9Sstevel@tonic-gate errno = EINVAL;
1417c478bd9Sstevel@tonic-gate else
1427c478bd9Sstevel@tonic-gate errno = ENOTTY;
1437c478bd9Sstevel@tonic-gate return (-1);
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate hp = (HEADER *) answer;
147*9525b14bSRao Shoaib if (hp->tc && !usingTCP && (statp->options & RES_IGNTC) == 0U) {
1487c478bd9Sstevel@tonic-gate nstatp->options &= ~RES_IGNTC;
1497c478bd9Sstevel@tonic-gate usingTCP = 1;
1507c478bd9Sstevel@tonic-gate goto retry;
1517c478bd9Sstevel@tonic-gate }
152*9525b14bSRao Shoaib Dprint((statp->options & RES_DEBUG) ||
153*9525b14bSRao Shoaib ((statp->pfcode & RES_PRF_REPLY) &&
154*9525b14bSRao Shoaib (statp->pfcode & RES_PRF_HEAD1)),
155*9525b14bSRao Shoaib (stdout, ";; got answer:\n"));
156*9525b14bSRao Shoaib
157*9525b14bSRao Shoaib DprintQ((statp->options & RES_DEBUG) ||
158*9525b14bSRao Shoaib (statp->pfcode & RES_PRF_REPLY),
159*9525b14bSRao Shoaib (stdout, "%s", ""),
160*9525b14bSRao Shoaib answer, (anslen > len) ? len : anslen);
161*9525b14bSRao Shoaib
162*9525b14bSRao Shoaib Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n"));
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate free (nstatp);
1657c478bd9Sstevel@tonic-gate free (newmsg);
1667c478bd9Sstevel@tonic-gate dst_free_key(dstkey);
167*9525b14bSRao Shoaib return (len);
1687c478bd9Sstevel@tonic-gate }
169*9525b14bSRao Shoaib
170*9525b14bSRao Shoaib /*! \file */
171