xref: /onnv-gate/usr/src/lib/libresolv2/common/resolv/res_sendsigned.c (revision 11038:74b12212b8a2)
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