[BACK]Return to res_sendsigned.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libresolv

File: [cvs.NetBSD.org] / src / lib / libresolv / res_sendsigned.c (download)

Revision 1.1, Thu Nov 15 18:48:49 2012 UTC (7 years, 6 months ago) by christos
Branch: MAIN
CVS Tags: yamt-pagecache-base9, yamt-pagecache-base8, yamt-pagecache-base7, tls-maxphys-base, tls-earlyentropy-base, tls-earlyentropy, riastradh-xf86-video-intel-2-7-1-pre-2-21-15, riastradh-drm2-base3, riastradh-drm2-base2, riastradh-drm2-base1, riastradh-drm2-base, riastradh-drm2, prg-localcount2-base3, prg-localcount2-base2, prg-localcount2-base1, prg-localcount2-base, prg-localcount2, phil-wifi-base, phil-wifi-20200421, phil-wifi-20200411, phil-wifi-20200406, phil-wifi-20191119, phil-wifi-20190609, phil-wifi, pgoyette-localcount-base, pgoyette-localcount-20170426, pgoyette-localcount-20170320, pgoyette-localcount-20170107, pgoyette-localcount-20161104, pgoyette-localcount-20160806, pgoyette-localcount-20160726, pgoyette-localcount, pgoyette-compat-merge-20190127, pgoyette-compat-base, pgoyette-compat-20190127, pgoyette-compat-20190118, pgoyette-compat-1226, pgoyette-compat-1126, pgoyette-compat-1020, pgoyette-compat-0930, pgoyette-compat-0906, pgoyette-compat-0728, pgoyette-compat-0625, pgoyette-compat-0521, pgoyette-compat-0502, pgoyette-compat-0422, pgoyette-compat-0415, pgoyette-compat-0407, pgoyette-compat-0330, pgoyette-compat-0322, pgoyette-compat-0315, pgoyette-compat, perseant-stdc-iso10646-base, perseant-stdc-iso10646, netbsd-9-base, netbsd-9-0-RELEASE, netbsd-9-0-RC2, netbsd-9-0-RC1, netbsd-9, netbsd-8-base, netbsd-8-2-RELEASE, netbsd-8-1-RELEASE, netbsd-8-1-RC1, netbsd-8-0-RELEASE, netbsd-8-0-RC2, netbsd-8-0-RC1, netbsd-8, netbsd-7-nhusb-base-20170116, netbsd-7-nhusb-base, netbsd-7-nhusb, netbsd-7-base, netbsd-7-2-RELEASE, netbsd-7-1-RELEASE, netbsd-7-1-RC2, netbsd-7-1-RC1, netbsd-7-1-2-RELEASE, netbsd-7-1-1-RELEASE, netbsd-7-1, netbsd-7-0-RELEASE, netbsd-7-0-RC3, netbsd-7-0-RC2, netbsd-7-0-RC1, netbsd-7-0-2-RELEASE, netbsd-7-0-1-RELEASE, netbsd-7-0, netbsd-7, matt-nb8-mediatek-base, matt-nb8-mediatek, localcount-20160914, is-mlppp-base, is-mlppp, bouyer-socketcan-base1, bouyer-socketcan-base, bouyer-socketcan, agc-symver-base, agc-symver, HEAD
Branch point for: yamt-pagecache, tls-maxphys, netbsd-6

Make libresolv handle the part that libc does not handle, update records
and signing.

/*	$NetBSD: res_sendsigned.c,v 1.1 2012/11/15 18:48:49 christos Exp $	*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: res_sendsigned.c,v 1.1 2012/11/15 18:48:49 christos Exp $");

#include "port_before.h"
#include "fd_setsize.h"

#include <sys/types.h>
#include <sys/param.h>

#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>

#include <isc/dst.h>

#include <errno.h>
#include <netdb.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "port_after.h"

#include "res_debug.h"


/*% res_nsendsigned */
int
res_nsendsigned(res_state statp, const u_char *msg, int msglen,
		ns_tsig_key *key, u_char *answer, int anslen)
{
	res_state nstatp;
	DST_KEY *dstkey;
	int usingTCP = 0;
	u_char *newmsg;
	int newmsglen, bufsize, siglen;
	u_char sig[64];
	HEADER *hp;
	time_t tsig_time;
	int ret;
	int len;

	dst_init();

	nstatp = (res_state) malloc(sizeof(*statp));
	if (nstatp == NULL) {
		errno = ENOMEM;
		return (-1);
	}
	memcpy(nstatp, statp, sizeof(*statp));

	bufsize = msglen + 1024;
	newmsg = (u_char *) malloc(bufsize);
	if (newmsg == NULL) {
		free(nstatp);
		errno = ENOMEM;
		return (-1);
	}
	memcpy(newmsg, msg, msglen);
	newmsglen = msglen;

	if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1)
		dstkey = NULL;
	else
		dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5,
					   NS_KEY_TYPE_AUTH_ONLY,
					   NS_KEY_PROT_ANY,
					   key->data, key->len);
	if (dstkey == NULL) {
		errno = EINVAL;
		free(nstatp);
		free(newmsg);
		return (-1);
	}

	nstatp->nscount = 1;
	siglen = sizeof(sig);
	ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0,
		      sig, &siglen, 0);
	if (ret < 0) {
		free (nstatp);
		free (newmsg);
		dst_free_key(dstkey);
		if (ret == NS_TSIG_ERROR_NO_SPACE)
			errno  = EMSGSIZE;
		else if (ret == -1)
			errno  = EINVAL;
		return (ret);
	}

	if (newmsglen > PACKETSZ || nstatp->options & RES_USEVC)
		usingTCP = 1;
	if (usingTCP == 0)
		nstatp->options |= RES_IGNTC;
	else
		nstatp->options |= RES_USEVC;
	/*
	 * Stop res_send printing the answer.
	 */
	nstatp->options &= ~RES_DEBUG;
	nstatp->pfcode &= ~RES_PRF_REPLY;

retry:

	len = res_nsend(nstatp, newmsg, newmsglen, answer, anslen);
	if (len < 0) {
		free (nstatp);
		free (newmsg);
		dst_free_key(dstkey);
		return (len);
	}

	ret = ns_verify(answer, &len, dstkey, sig, siglen,
	    NULL, NULL, &tsig_time, (nstatp->options & RES_KEEPTSIG) != 0);
	if (ret != 0) {
		Dprint((statp->options & RES_DEBUG) ||
		       ((statp->pfcode & RES_PRF_REPLY) &&
			(statp->pfcode & RES_PRF_HEAD1)),
		       (stdout, ";; got answer:\n"));

		DprintQ((statp->options & RES_DEBUG) ||
			(statp->pfcode & RES_PRF_REPLY),
			(stdout, "%s", ""),
			answer, (anslen > len) ? len : anslen);

		if (ret > 0) {
			Dprint(statp->pfcode & RES_PRF_REPLY,
			       (stdout, ";; server rejected TSIG (%s)\n",
				p_rcode(ret)));
		} else {
			Dprint(statp->pfcode & RES_PRF_REPLY,
			       (stdout, ";; TSIG invalid (%s)\n",
				p_rcode(-ret)));
		}

		free (nstatp);
		free (newmsg);
		dst_free_key(dstkey);
		if (ret == -1)
			errno = EINVAL;
		else
			errno = ENOTTY;
		return (-1);
	}

	hp = (HEADER *)(void *)answer;
	if (hp->tc && !usingTCP && (statp->options & RES_IGNTC) == 0U) {
		nstatp->options &= ~RES_IGNTC;
		usingTCP = 1;
		goto retry;
	}
	Dprint((statp->options & RES_DEBUG) ||
	       ((statp->pfcode & RES_PRF_REPLY) &&
		(statp->pfcode & RES_PRF_HEAD1)),
	       (stdout, ";; got answer:\n"));

	DprintQ((statp->options & RES_DEBUG) ||
		(statp->pfcode & RES_PRF_REPLY),
		(stdout, "%s", ""),
		answer, (anslen > len) ? len : anslen);

	Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n"));

	free (nstatp);
	free (newmsg);
	dst_free_key(dstkey);
	return (len);
}

/*! \file */