tsig.c revision 3b2efab212088496d5588ca5ed2d802c72d21a08
/*
* Copyright (C) 1999, 2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* $Id: tsig.c,v 1.77 2000/07/21 22:38:29 bwelling Exp $
* Principal Author: Brian Wellington
*/
#include <config.h>
#include <stdlib.h> /* Required for abs(). */
#include <dns/keyvalues.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
static dns_name_t hmacmd5_name;
static isc_result_t
static void
dns_tsig_inithmac(void) {
const char *str = "\010HMAC-MD5\007SIG-ALG\003REG\003INT";
}
{
isc_buffer_t b;
if (length > 0)
return (ISC_R_NOTFOUND);
else
return (ISC_R_NOMEMORY);
if (ret != ISC_R_SUCCESS)
goto cleanup_key;
if (ret != ISC_R_SUCCESS)
goto cleanup_name;
goto cleanup_algorithm;
}
if (ret != ISC_R_SUCCESS) {
goto cleanup_algorithm;
}
}
else
if (length > 0) {
isc_buffer_add(&b, length);
if (ret != ISC_R_SUCCESS)
goto cleanup_algorithm;
(void *)&tmp);
if (ret == ISC_R_SUCCESS) {
ret = ISC_R_EXISTS;
goto cleanup_algorithm;
}
ret == DNS_R_PARTIALMATCH);
if (ret != ISC_R_SUCCESS) {
ret = ISC_R_EXISTS;
goto cleanup_algorithm;
}
}
}
if (ret != ISC_R_SUCCESS) {
"isc_mutex_init() failed: %s",
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
return (ret);
}
void
}
static void
}
}
void
if (should_free)
}
void
}
unsigned char data[128];
isc_region_t r, r2;
/*
* If this is a response, there should be a query tsig.
*/
return (DNS_R_EXPECTEDTSIG);
if (is_response(msg))
else
}
else {
goto cleanup_other;
}
0xFFFFFFFF));
}
unsigned char header[DNS_MESSAGE_HEADERLEN];
unsigned int sigsize;
if (ret != ISC_R_SUCCESS)
goto cleanup_other;
/*
* If this is a response, digest the query signature.
*/
if (is_response(msg)) {
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
NULL);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
if (isc_buffer_availablelength(&databuf) <
{
ret = ISC_R_NOSPACE;
goto cleanup_context;
}
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
/*
* Digest the header.
*/
isc_buffer_usedregion(&headerbuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest the remainder of the message.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
if (msg->tcp_continuation == 0) {
/*
* Digest the name, class, ttl, alg.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
/* Digest the timesigned and fudge */
32));
0xFFFFFFFF));
}
else {
(isc_uint16_t)(querysigned >>
32));
0xFFFFFFFF));
}
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
if (msg->tcp_continuation == 0) {
/*
* Digest the error and other data length.
*/
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest the error and other data.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
}
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
goto cleanup_context;
}
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
}
else {
}
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
if (ret != ISC_R_SUCCESS)
goto cleanup_dynbuf;
}
}
if (ret != ISC_R_SUCCESS)
goto cleanup_dynbuf;
if (ret != ISC_R_SUCCESS)
goto cleanup_dynbuf;
if (ret != ISC_R_SUCCESS)
goto cleanup_dynbuf;
if (ret != ISC_R_SUCCESS)
goto cleanup_dynbuf;
return (ISC_R_SUCCESS);
return (ret);
}
{
unsigned char data[32];
unsigned char header[DNS_MESSAGE_HEADERLEN];
if (msg->tcp_continuation)
/*
* There should be a TSIG record...
*/
return (DNS_R_EXPECTEDTSIG);
/*
* If this is a response and there's no key or query TSIG, there
* shouldn't be one on the response.
*/
if (is_response(msg) &&
return (DNS_R_UNEXPECTEDTSIG);
/*
* If we're here, we know the message is well formed and contains a
* TSIG record.
*/
if (ret != ISC_R_SUCCESS)
return (ret);
if (ret != ISC_R_SUCCESS)
return (ret);
if (is_response(msg)) {
if (ret != ISC_R_SUCCESS)
return (ret);
if (ret != ISC_R_SUCCESS)
return (ret);
}
/*
* Do the key name and algorithm match that of the query?
*/
if (is_response(msg) &&
{
return (DNS_R_TSIGVERIFYFAILURE);
}
/*
* Get the current time.
*/
/*
* Find dns_tsigkey_t based on keyname.
*/
if (ret != ISC_R_SUCCESS) {
if (ret != ISC_R_SUCCESS)
return (ret);
return (DNS_R_TSIGVERIFYFAILURE);
}
}
/*
* Is the time ok?
*/
return (DNS_R_TSIGVERIFYFAILURE);
}
if (ret != ISC_R_SUCCESS)
goto cleanup_key;
if (is_response(msg)) {
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
}
/*
* Extract the header.
*/
isc_buffer_usedregion(source, &r);
/*
* Decrement the additional field counter.
*/
/*
* Put in the original id.
*/
/*
* Digest the modified header.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest all non-TSIG records.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest the key name.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest the key algorithm.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
>> 32));
& 0xFFFFFFFF));
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
if (ret == DST_R_VERIFYFAILURE) {
goto cleanup_context;
}
else if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
{
return (DNS_R_TSIGVERIFYFAILURE);
}
return (DNS_R_TSIGERRORSET);
return (ISC_R_SUCCESS);
if (dns_tsigkey_empty(tsigkey))
return (ret);
}
static isc_result_t
unsigned char data[32];
unsigned char header[DNS_MESSAGE_HEADERLEN];
/*
* Extract and parse the previous TSIG
*/
if (ret != ISC_R_SUCCESS)
return (ret);
if (ret != ISC_R_SUCCESS)
return (ret);
/*
* If there is a TSIG in this message, do some checks.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_querystruct;
if (ret != ISC_R_SUCCESS)
goto cleanup_querystruct;
/*
* Do the key name and algorithm match that of the query?
*/
{
goto cleanup_querystruct;
}
/*
* Is the time ok?
*/
goto cleanup_querystruct;
}
}
if (ret != ISC_R_SUCCESS)
goto cleanup_querystruct;
/*
* Digest the length of the query signature
*/
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest the data of the query signature
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
}
/*
* Extract the header.
*/
isc_buffer_usedregion(source, &r);
/*
* Decrement the additional field counter if necessary.
*/
if (has_tsig) {
}
/*
* Put in the original id.
*/
/* XXX Can TCP transfers be forwarded? How would that work? */
if (has_tsig) {
}
/*
* Digest the modified header.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest all non-TSIG records.
*/
if (has_tsig)
else
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* Digest the time signed and fudge.
*/
if (has_tsig) {
>> 32));
& 0xFFFFFFFF));
isc_buffer_usedregion(&databuf, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
else
goto cleanup_context;
}
if (ret == DST_R_VERIFYFAILURE) {
goto cleanup_context;
}
else if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
return (ISC_R_SUCCESS);
return (ret);
}
{
return (ISC_R_NOTFOUND);
}
return (ISC_R_NOTFOUND);
}
/*
* The key has expired.
*/
return (ISC_R_NOTFOUND);
}
return (ISC_R_SUCCESS);
}
static void
}
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS) {
"isc_rwlock_init() failed: %s",
return (ISC_R_UNEXPECTED);
}
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_SUCCESS);
}
void
}