cc.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
/*
* Portions Copyright (C) 2001-2007, 2012-2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Portions Copyright (C) 2001 Nominum, Inc.
*
* 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 ISC AND NOMINUM DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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.
*/
/*! \file */
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <isc/assertions.h>
#define MAX_TAGS 256
#define DUP_LIFETIME 900
typedef isccc_sexpr_t *sexpr_ptr;
static unsigned char auth_hmd5[] = {
0x05, 0x5f, 0x61, 0x75, 0x74, 0x68, /*%< len + _auth */
ISCCC_CCMSGTYPE_TABLE, /*%< message type */
0x00, 0x00, 0x00, 0x20, /*%< length == 32 */
0x04, 0x68, 0x6d, 0x64, 0x35, /*%< len + hmd5 */
ISCCC_CCMSGTYPE_BINARYDATA, /*%< message type */
0x00, 0x00, 0x00, 0x16, /*%< length == 22 */
/*
* The base64 encoding of one of our HMAC-MD5 signatures is
* 22 bytes.
*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#define HMD5_LENGTH 22
static unsigned char auth_hsha[] = {
0x05, 0x5f, 0x61, 0x75, 0x74, 0x68, /*%< len + _auth */
ISCCC_CCMSGTYPE_TABLE, /*%< message type */
0x00, 0x00, 0x00, 0x63, /*%< length == 99 */
0x04, 0x68, 0x73, 0x68, 0x61, /*%< len + hsha */
ISCCC_CCMSGTYPE_BINARYDATA, /*%< message type */
0x00, 0x00, 0x00, 0x59, /*%< length == 89 */
0x00, /*%< algorithm */
/*
* The base64 encoding of one of our HMAC-SHA* signatures is
* 88 bytes.
*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#define HSHA_LENGTH 88
static isc_result_t
static isc_result_t
static isc_result_t
unsigned int len;
if (isccc_sexpr_binaryp(elt)) {
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
} else if (isccc_alist_alistp(elt)) {
unsigned int used;
isc_buffer_t b;
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
/*
* Emit a placeholder length.
*/
isc_buffer_putuint32(*buffer, 0);
/*
* Emit the table.
*/
if (result != ISC_R_SUCCESS)
return (result);
/*
* 'len' is 4 bytes too big, since it counts
* the placeholder length too. Adjust and
* emit.
*/
len -= 4;
isc_buffer_putuint32(&b, len);
} else if (isccc_sexpr_listp(elt)) {
unsigned int used;
isc_buffer_t b;
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
/*
* Emit a placeholder length.
*/
isc_buffer_putuint32(*buffer, 0);
/*
* Emit the list.
*/
if (result != ISC_R_SUCCESS)
return (result);
/*
* 'len' is 4 bytes too big, since it counts
* the placeholder length too. Adjust and
* emit.
*/
len -= 4;
isc_buffer_putuint32(&b, len);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
char *ks;
unsigned int len;
k = ISCCC_SEXPR_CAR(kv);
ks = isccc_sexpr_tostring(k);
v = ISCCC_SEXPR_CDR(kv);
/*
* Emit the key name.
*/
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
/*
* Emit the value.
*/
if (result != ISC_R_SUCCESS)
return (result);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
if (result != ISC_R_SUCCESS)
return (result);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
{
union {
} ctx;
unsigned char digest[ISC_SHA512_DIGESTLENGTH];
switch (algorithm) {
case ISCCC_ALG_HMACMD5:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA1:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA224:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA256:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA384:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA512:
REGION_SIZE(*secret));
break;
default:
return (ISC_R_FAILURE);
}
if (result != ISC_R_SUCCESS)
return (result);
if (algorithm == ISCCC_ALG_HMACMD5)
else
return (ISC_R_SUCCESS);
}
{
unsigned int hmac_base, signed_base;
sizeof(auth_hmd5) :
sizeof(auth_hsha)));
if (result != ISC_R_SUCCESS)
return (ISC_R_NOSPACE);
/*
* Emit protocol version.
*/
/*
* Emit _auth section with zeroed HMAC signature.
* We'll replace the zeros with the real signature once
* we know what it is.
*/
if (algorithm == ISCCC_ALG_HMACMD5) {
} else {
unsigned char *hmac_alg;
HSHA_OFFSET - 1;
}
} else
hmac_base = 0;
/*
* Delete any existing _auth section so that we don't try
* to encode it.
*/
/*
* Emit the message.
*/
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
}
static isc_result_t
{
union {
} ctx;
unsigned char digest[ISC_SHA512_DIGESTLENGTH];
/*
* Extract digest.
*/
if (!isccc_alist_alistp(_auth))
return (ISC_R_FAILURE);
if (algorithm == ISCCC_ALG_HMACMD5)
else
if (!isccc_sexpr_binaryp(hmac))
return (ISC_R_FAILURE);
/*
* Compute digest.
*/
switch (algorithm) {
case ISCCC_ALG_HMACMD5:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA1:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA224:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA256:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA384:
REGION_SIZE(*secret));
break;
case ISCCC_ALG_HMACSHA512:
REGION_SIZE(*secret));
break;
default:
return (ISC_R_FAILURE);
}
if (result != ISC_R_SUCCESS)
return (result);
/*
* Verify.
*/
if (algorithm == ISCCC_ALG_HMACMD5) {
unsigned char *value;
return (ISCCC_R_BADAUTH);
return (ISCCC_R_BADAUTH);
} else {
unsigned char *value;
/*
* Note: with non-MD5 algorithms, there's an extra octet
* to identify which algorithm is in use.
*/
return (ISCCC_R_BADAUTH);
return (ISCCC_R_BADAUTH);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
static isc_result_t
static isc_result_t
unsigned int msgtype;
return (ISC_R_UNEXPECTEDEND);
return (ISC_R_UNEXPECTEDEND);
if (msgtype == ISCCC_CCMSGTYPE_BINARYDATA) {
} else
} else if (msgtype == ISCCC_CCMSGTYPE_TABLE)
else if (msgtype == ISCCC_CCMSGTYPE_LIST)
else
return (result);
}
static isc_result_t
{
char key[256];
unsigned char *checksum_rstart;
alist = isccc_alist_create();
return (ISC_R_NOMEMORY);
while (!REGION_EMPTY(*source)) {
goto bad;
}
if (result != ISC_R_SUCCESS)
goto bad;
goto bad;
}
}
if (checksum_rstart != NULL)
(unsigned int)
else
} else
bad:
if (result == ISC_R_SUCCESS)
else
return (result);
}
static isc_result_t
while (!REGION_EMPTY(*source)) {
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_NOMEMORY);
}
}
return (ISC_R_SUCCESS);
}
{
unsigned int size;
if (size < 4)
return (ISC_R_UNEXPECTEDEND);
if (version != 1)
return (ISCCC_R_UNKNOWNVERSION);
}
static isc_result_t
{
if (version != 1)
return (ISCCC_R_UNKNOWNVERSION);
alist = isccc_alist_create();
return (ISC_R_NOMEMORY);
_ctrl = isccc_alist_create();
goto bad;
goto bad;
}
_data = isccc_alist_create();
goto bad;
goto bad;
}
(want_expires &&
goto bad;
goto bad;
goto bad;
return (ISC_R_SUCCESS);
bad:
return (result);
}
{
}
{
isccc_time_t t;
if (!isccc_alist_alistp(_ctrl) ||
return (ISC_R_FAILURE);
/*
* _frm and _to are optional.
*/
/*
* Create the ack.
*/
if (result != ISC_R_SUCCESS)
return (result);
goto bad;
}
goto bad;
}
return (ISC_R_SUCCESS);
bad:
return (result);
}
if (!isccc_alist_alistp(_ctrl))
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_FALSE);
}
if (!isccc_alist_alistp(_ctrl))
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_FALSE);
}
{
return (ISC_R_FAILURE);
/*
* _frm and _to are optional.
*/
/*
* Create the response.
*/
&alist);
if (result != ISC_R_SUCCESS)
return (result);
goto bad;
}
goto bad;
}
{
goto bad;
}
return (ISC_R_SUCCESS);
bad:
return (result);
}
}
char b[100];
snprintf(b, sizeof(b), "%u", i);
r.rstart = (unsigned char *)b;
}
isccc_sexpr_t *kv, *v;
v = ISCCC_SEXPR_CDR(kv);
if (isccc_sexpr_binaryp(v)) {
*strp = isccc_sexpr_tostring(v);
return (ISC_R_SUCCESS);
} else
return (ISC_R_EXISTS);
}
return (ISC_R_NOTFOUND);
}
{
isccc_sexpr_t *kv, *v;
v = ISCCC_SEXPR_CDR(kv);
if (isccc_sexpr_binaryp(v)) {
*uintp = (isc_uint32_t)
NULL, 10);
return (ISC_R_SUCCESS);
} else
return (ISC_R_EXISTS);
}
return (ISC_R_NOTFOUND);
}
static void
void *arg)
{
}
static isc_boolean_t
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_TRUE);
}
symtabp));
}
void
}
static isc_boolean_t
has_whitespace(const char *str) {
char c;
return (ISC_FALSE);
while ((c = *str++) != '\0') {
if (c == ' ' || c == '\t' || c == '\n')
return (ISC_TRUE);
}
return (ISC_FALSE);
}
{
const char *_frm;
const char *_to;
char *key;
if (!isccc_alist_alistp(_ctrl) ||
return (ISC_R_FAILURE);
/*
* _frm and _to are optional.
*/
_frm = "";
else
_to = "";
else
/*
* Ensure there is no newline in any of the strings. This is so
* we can write them to a file later.
*/
return (ISC_R_FAILURE);
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_SUCCESS);
}