diff options
Diffstat (limited to 'contrib/bind9/lib/isccc/cc.c')
-rw-r--r-- | contrib/bind9/lib/isccc/cc.c | 818 |
1 files changed, 0 insertions, 818 deletions
diff --git a/contrib/bind9/lib/isccc/cc.c b/contrib/bind9/lib/isccc/cc.c deleted file mode 100644 index e65349e..0000000 --- a/contrib/bind9/lib/isccc/cc.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Portions Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (C) 2001-2003 Internet Software Consortium. - * Portions Copyright (C) 2001 Nominum, Inc. - * - * 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 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. - */ - -/* $Id: cc.c,v 1.10.18.5 2006/12/07 23:57:58 marka Exp $ */ - -/*! \file */ - -#include <config.h> - -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <isc/assertions.h> -#include <isc/hmacmd5.h> -#include <isc/print.h> -#include <isc/stdlib.h> - -#include <isccc/alist.h> -#include <isccc/base64.h> -#include <isccc/cc.h> -#include <isccc/result.h> -#include <isccc/sexpr.h> -#include <isccc/symtab.h> -#include <isccc/symtype.h> -#include <isccc/util.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_OFFSET 21 /*%< 21 = 6 + 1 + 4 + 5 + 1 + 4 */ -#define HMD5_LENGTH 22 - -static isc_result_t -table_towire(isccc_sexpr_t *alist, isccc_region_t *target); - -static isc_result_t -list_towire(isccc_sexpr_t *alist, isccc_region_t *target); - -static isc_result_t -value_towire(isccc_sexpr_t *elt, isccc_region_t *target) -{ - size_t len; - unsigned char *lenp; - isccc_region_t *vr; - isc_result_t result; - - if (isccc_sexpr_binaryp(elt)) { - vr = isccc_sexpr_tobinary(elt); - len = REGION_SIZE(*vr); - if (REGION_SIZE(*target) < 1 + 4 + len) - return (ISC_R_NOSPACE); - PUT8(ISCCC_CCMSGTYPE_BINARYDATA, target->rstart); - PUT32(len, target->rstart); - if (REGION_SIZE(*target) < len) - return (ISC_R_NOSPACE); - PUT_MEM(vr->rstart, len, target->rstart); - } else if (isccc_alist_alistp(elt)) { - if (REGION_SIZE(*target) < 1 + 4) - return (ISC_R_NOSPACE); - PUT8(ISCCC_CCMSGTYPE_TABLE, target->rstart); - /* - * Emit a placeholder length. - */ - lenp = target->rstart; - PUT32(0, target->rstart); - /* - * Emit the table. - */ - result = table_towire(elt, target); - if (result != ISC_R_SUCCESS) - return (result); - len = (size_t)(target->rstart - lenp); - /* - * 'len' is 4 bytes too big, since it counts - * the placeholder length too. Adjust and - * emit. - */ - INSIST(len >= 4U); - len -= 4; - PUT32(len, lenp); - } else if (isccc_sexpr_listp(elt)) { - if (REGION_SIZE(*target) < 1 + 4) - return (ISC_R_NOSPACE); - PUT8(ISCCC_CCMSGTYPE_LIST, target->rstart); - /* - * Emit a placeholder length and count. - */ - lenp = target->rstart; - PUT32(0, target->rstart); - /* - * Emit the list. - */ - result = list_towire(elt, target); - if (result != ISC_R_SUCCESS) - return (result); - len = (size_t)(target->rstart - lenp); - /* - * 'len' is 4 bytes too big, since it counts - * the placeholder length. Adjust and emit. - */ - INSIST(len >= 4U); - len -= 4; - PUT32(len, lenp); - } - - return (ISC_R_SUCCESS); -} - -static isc_result_t -table_towire(isccc_sexpr_t *alist, isccc_region_t *target) -{ - isccc_sexpr_t *kv, *elt, *k, *v; - char *ks; - isc_result_t result; - size_t len; - - for (elt = isccc_alist_first(alist); - elt != NULL; - elt = ISCCC_SEXPR_CDR(elt)) { - kv = ISCCC_SEXPR_CAR(elt); - k = ISCCC_SEXPR_CAR(kv); - ks = isccc_sexpr_tostring(k); - v = ISCCC_SEXPR_CDR(kv); - len = strlen(ks); - INSIST(len <= 255U); - /* - * Emit the key name. - */ - if (REGION_SIZE(*target) < 1 + len) - return (ISC_R_NOSPACE); - PUT8(len, target->rstart); - PUT_MEM(ks, len, target->rstart); - /* - * Emit the value. - */ - result = value_towire(v, target); - if (result != ISC_R_SUCCESS) - return (result); - } - - return (ISC_R_SUCCESS); -} - -static isc_result_t -list_towire(isccc_sexpr_t *list, isccc_region_t *target) -{ - isc_result_t result; - - while (list != NULL) { - result = value_towire(ISCCC_SEXPR_CAR(list), target); - if (result != ISC_R_SUCCESS) - return (result); - list = ISCCC_SEXPR_CDR(list); - } - - return (ISC_R_SUCCESS); -} - -static isc_result_t -sign(unsigned char *data, unsigned int length, unsigned char *hmd5, - isccc_region_t *secret) -{ - isc_hmacmd5_t ctx; - isc_result_t result; - isccc_region_t source, target; - unsigned char digest[ISC_MD5_DIGESTLENGTH]; - unsigned char digestb64[ISC_MD5_DIGESTLENGTH * 4]; - - isc_hmacmd5_init(&ctx, secret->rstart, REGION_SIZE(*secret)); - isc_hmacmd5_update(&ctx, data, length); - isc_hmacmd5_sign(&ctx, digest); - source.rstart = digest; - source.rend = digest + ISC_MD5_DIGESTLENGTH; - target.rstart = digestb64; - target.rend = digestb64 + ISC_MD5_DIGESTLENGTH * 4; - result = isccc_base64_encode(&source, 64, "", &target); - if (result != ISC_R_SUCCESS) - return (result); - PUT_MEM(digestb64, HMD5_LENGTH, hmd5); - - return (ISC_R_SUCCESS); -} - -isc_result_t -isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target, - isccc_region_t *secret) -{ - unsigned char *hmd5_rstart, *signed_rstart; - isc_result_t result; - - if (REGION_SIZE(*target) < 4 + sizeof(auth_hmd5)) - return (ISC_R_NOSPACE); - /* - * Emit protocol version. - */ - PUT32(1, target->rstart); - if (secret != NULL) { - /* - * Emit _auth section with zeroed HMAC-MD5 signature. - * We'll replace the zeros with the real signature once - * we know what it is. - */ - hmd5_rstart = target->rstart + HMD5_OFFSET; - PUT_MEM(auth_hmd5, sizeof(auth_hmd5), target->rstart); - } else - hmd5_rstart = NULL; - signed_rstart = target->rstart; - /* - * Delete any existing _auth section so that we don't try - * to encode it. - */ - isccc_alist_delete(alist, "_auth"); - /* - * Emit the message. - */ - result = table_towire(alist, target); - if (result != ISC_R_SUCCESS) - return (result); - if (secret != NULL) - return (sign(signed_rstart, (target->rstart - signed_rstart), - hmd5_rstart, secret)); - return (ISC_R_SUCCESS); -} - -static isc_result_t -verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, - isccc_region_t *secret) -{ - isc_hmacmd5_t ctx; - isccc_region_t source; - isccc_region_t target; - isc_result_t result; - isccc_sexpr_t *_auth, *hmd5; - unsigned char digest[ISC_MD5_DIGESTLENGTH]; - unsigned char digestb64[ISC_MD5_DIGESTLENGTH * 4]; - - /* - * Extract digest. - */ - _auth = isccc_alist_lookup(alist, "_auth"); - if (_auth == NULL) - return (ISC_R_FAILURE); - hmd5 = isccc_alist_lookup(_auth, "hmd5"); - if (hmd5 == NULL) - return (ISC_R_FAILURE); - /* - * Compute digest. - */ - isc_hmacmd5_init(&ctx, secret->rstart, REGION_SIZE(*secret)); - isc_hmacmd5_update(&ctx, data, length); - isc_hmacmd5_sign(&ctx, digest); - source.rstart = digest; - source.rend = digest + ISC_MD5_DIGESTLENGTH; - target.rstart = digestb64; - target.rend = digestb64 + ISC_MD5_DIGESTLENGTH * 4; - result = isccc_base64_encode(&source, 64, "", &target); - if (result != ISC_R_SUCCESS) - return (result); - /* - * Strip trailing == and NUL terminate target. - */ - target.rstart -= 2; - *target.rstart++ = '\0'; - /* - * Verify. - */ - if (strcmp((char *)digestb64, isccc_sexpr_tostring(hmd5)) != 0) - return (ISCCC_R_BADAUTH); - - return (ISC_R_SUCCESS); -} - -static isc_result_t -table_fromwire(isccc_region_t *source, isccc_region_t *secret, - isccc_sexpr_t **alistp); - -static isc_result_t -list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp); - -static isc_result_t -value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) -{ - unsigned int msgtype; - isc_uint32_t len; - isccc_sexpr_t *value; - isccc_region_t active; - isc_result_t result; - - if (REGION_SIZE(*source) < 1 + 4) - return (ISC_R_UNEXPECTEDEND); - GET8(msgtype, source->rstart); - GET32(len, source->rstart); - if (REGION_SIZE(*source) < len) - return (ISC_R_UNEXPECTEDEND); - active.rstart = source->rstart; - active.rend = active.rstart + len; - source->rstart = active.rend; - if (msgtype == ISCCC_CCMSGTYPE_BINARYDATA) { - value = isccc_sexpr_frombinary(&active); - if (value != NULL) { - *valuep = value; - result = ISC_R_SUCCESS; - } else - result = ISC_R_NOMEMORY; - } else if (msgtype == ISCCC_CCMSGTYPE_TABLE) - result = table_fromwire(&active, NULL, valuep); - else if (msgtype == ISCCC_CCMSGTYPE_LIST) - result = list_fromwire(&active, valuep); - else - result = ISCCC_R_SYNTAX; - - return (result); -} - -static isc_result_t -table_fromwire(isccc_region_t *source, isccc_region_t *secret, - isccc_sexpr_t **alistp) -{ - char key[256]; - isc_uint32_t len; - isc_result_t result; - isccc_sexpr_t *alist, *value; - isc_boolean_t first_tag; - unsigned char *checksum_rstart; - - REQUIRE(alistp != NULL && *alistp == NULL); - - checksum_rstart = NULL; - first_tag = ISC_TRUE; - alist = isccc_alist_create(); - if (alist == NULL) - return (ISC_R_NOMEMORY); - - while (!REGION_EMPTY(*source)) { - GET8(len, source->rstart); - if (REGION_SIZE(*source) < len) { - result = ISC_R_UNEXPECTEDEND; - goto bad; - } - GET_MEM(key, len, source->rstart); - key[len] = '\0'; /* Ensure NUL termination. */ - value = NULL; - result = value_fromwire(source, &value); - if (result != ISC_R_SUCCESS) - goto bad; - if (isccc_alist_define(alist, key, value) == NULL) { - result = ISC_R_NOMEMORY; - goto bad; - } - if (first_tag && secret != NULL && strcmp(key, "_auth") == 0) - checksum_rstart = source->rstart; - first_tag = ISC_FALSE; - } - - *alistp = alist; - - if (secret != NULL) { - if (checksum_rstart != NULL) - return (verify(alist, checksum_rstart, - (source->rend - checksum_rstart), - secret)); - return (ISCCC_R_BADAUTH); - } - - return (ISC_R_SUCCESS); - - bad: - isccc_sexpr_free(&alist); - - return (result); -} - -static isc_result_t -list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp) -{ - isccc_sexpr_t *list, *value; - isc_result_t result; - - list = NULL; - while (!REGION_EMPTY(*source)) { - value = NULL; - result = value_fromwire(source, &value); - if (result != ISC_R_SUCCESS) { - isccc_sexpr_free(&list); - return (result); - } - if (isccc_sexpr_addtolist(&list, value) == NULL) { - isccc_sexpr_free(&value); - isccc_sexpr_free(&list); - return (result); - } - } - - *listp = list; - - return (ISC_R_SUCCESS); -} - -isc_result_t -isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp, - isccc_region_t *secret) -{ - unsigned int size; - isc_uint32_t version; - - size = REGION_SIZE(*source); - if (size < 4) - return (ISC_R_UNEXPECTEDEND); - GET32(version, source->rstart); - if (version != 1) - return (ISCCC_R_UNKNOWNVERSION); - - return (table_fromwire(source, secret, alistp)); -} - -static isc_result_t -createmessage(isc_uint32_t version, const char *from, const char *to, - isc_uint32_t serial, isccc_time_t now, - isccc_time_t expires, isccc_sexpr_t **alistp, - isc_boolean_t want_expires) -{ - isccc_sexpr_t *alist, *_ctrl, *_data; - isc_result_t result; - - REQUIRE(alistp != NULL && *alistp == NULL); - - if (version != 1) - return (ISCCC_R_UNKNOWNVERSION); - - alist = isccc_alist_create(); - if (alist == NULL) - return (ISC_R_NOMEMORY); - - result = ISC_R_NOMEMORY; - - _ctrl = isccc_alist_create(); - if (_ctrl == NULL) - goto bad; - if (isccc_alist_define(alist, "_ctrl", _ctrl) == NULL) { - isccc_sexpr_free(&_ctrl); - goto bad; - } - - _data = isccc_alist_create(); - if (_data == NULL) - goto bad; - if (isccc_alist_define(alist, "_data", _data) == NULL) { - isccc_sexpr_free(&_data); - goto bad; - } - - if (isccc_cc_defineuint32(_ctrl, "_ser", serial) == NULL || - isccc_cc_defineuint32(_ctrl, "_tim", now) == NULL || - (want_expires && - isccc_cc_defineuint32(_ctrl, "_exp", expires) == NULL)) - goto bad; - if (from != NULL && - isccc_cc_definestring(_ctrl, "_frm", from) == NULL) - goto bad; - if (to != NULL && - isccc_cc_definestring(_ctrl, "_to", to) == NULL) - goto bad; - - *alistp = alist; - - return (ISC_R_SUCCESS); - - bad: - isccc_sexpr_free(&alist); - - return (result); -} - -isc_result_t -isccc_cc_createmessage(isc_uint32_t version, const char *from, const char *to, - isc_uint32_t serial, isccc_time_t now, - isccc_time_t expires, isccc_sexpr_t **alistp) -{ - return (createmessage(version, from, to, serial, now, expires, - alistp, ISC_TRUE)); -} - -isc_result_t -isccc_cc_createack(isccc_sexpr_t *message, isc_boolean_t ok, - isccc_sexpr_t **ackp) -{ - char *_frm, *_to; - isc_uint32_t serial; - isccc_sexpr_t *ack, *_ctrl; - isc_result_t result; - isccc_time_t t; - - REQUIRE(ackp != NULL && *ackp == NULL); - - _ctrl = isccc_alist_lookup(message, "_ctrl"); - if (_ctrl == NULL || - isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS || - isccc_cc_lookupuint32(_ctrl, "_tim", &t) != ISC_R_SUCCESS) - return (ISC_R_FAILURE); - /* - * _frm and _to are optional. - */ - _frm = NULL; - (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm); - _to = NULL; - (void)isccc_cc_lookupstring(_ctrl, "_to", &_to); - /* - * Create the ack. - */ - ack = NULL; - result = createmessage(1, _to, _frm, serial, t, 0, &ack, ISC_FALSE); - if (result != ISC_R_SUCCESS) - return (result); - - _ctrl = isccc_alist_lookup(ack, "_ctrl"); - if (_ctrl == NULL) - return (ISC_R_FAILURE); - if (isccc_cc_definestring(ack, "_ack", (ok) ? "1" : "0") == NULL) { - result = ISC_R_NOMEMORY; - goto bad; - } - - *ackp = ack; - - return (ISC_R_SUCCESS); - - bad: - isccc_sexpr_free(&ack); - - return (result); -} - -isc_boolean_t -isccc_cc_isack(isccc_sexpr_t *message) -{ - isccc_sexpr_t *_ctrl; - - _ctrl = isccc_alist_lookup(message, "_ctrl"); - if (_ctrl == NULL) - return (ISC_FALSE); - if (isccc_cc_lookupstring(_ctrl, "_ack", NULL) == ISC_R_SUCCESS) - return (ISC_TRUE); - return (ISC_FALSE); -} - -isc_boolean_t -isccc_cc_isreply(isccc_sexpr_t *message) -{ - isccc_sexpr_t *_ctrl; - - _ctrl = isccc_alist_lookup(message, "_ctrl"); - if (_ctrl == NULL) - return (ISC_FALSE); - if (isccc_cc_lookupstring(_ctrl, "_rpl", NULL) == ISC_R_SUCCESS) - return (ISC_TRUE); - return (ISC_FALSE); -} - -isc_result_t -isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now, - isccc_time_t expires, isccc_sexpr_t **alistp) -{ - char *_frm, *_to, *type; - isc_uint32_t serial; - isccc_sexpr_t *alist, *_ctrl, *_data; - isc_result_t result; - - REQUIRE(alistp != NULL && *alistp == NULL); - - _ctrl = isccc_alist_lookup(message, "_ctrl"); - _data = isccc_alist_lookup(message, "_data"); - if (_ctrl == NULL || - _data == NULL || - isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS || - isccc_cc_lookupstring(_data, "type", &type) != ISC_R_SUCCESS) - return (ISC_R_FAILURE); - /* - * _frm and _to are optional. - */ - _frm = NULL; - (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm); - _to = NULL; - (void)isccc_cc_lookupstring(_ctrl, "_to", &_to); - /* - * Create the response. - */ - alist = NULL; - result = isccc_cc_createmessage(1, _to, _frm, serial, now, expires, - &alist); - if (result != ISC_R_SUCCESS) - return (result); - _ctrl = isccc_alist_lookup(alist, "_ctrl"); - if (_ctrl == NULL) - return (ISC_R_FAILURE); - _data = isccc_alist_lookup(alist, "_data"); - if (_data == NULL) - return (ISC_R_FAILURE); - if (isccc_cc_definestring(_ctrl, "_rpl", "1") == NULL || - isccc_cc_definestring(_data, "type", type) == NULL) { - isccc_sexpr_free(&alist); - return (ISC_R_NOMEMORY); - } - - *alistp = alist; - - return (ISC_R_SUCCESS); -} - -isccc_sexpr_t * -isccc_cc_definestring(isccc_sexpr_t *alist, const char *key, const char *str) -{ - size_t len; - isccc_region_t r; - - len = strlen(str); - DE_CONST(str, r.rstart); - r.rend = r.rstart + len; - - return (isccc_alist_definebinary(alist, key, &r)); -} - -isccc_sexpr_t * -isccc_cc_defineuint32(isccc_sexpr_t *alist, const char *key, isc_uint32_t i) -{ - char b[100]; - size_t len; - isccc_region_t r; - - snprintf(b, sizeof(b), "%u", i); - len = strlen(b); - r.rstart = (unsigned char *)b; - r.rend = (unsigned char *)b + len; - - return (isccc_alist_definebinary(alist, key, &r)); -} - -isc_result_t -isccc_cc_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp) -{ - isccc_sexpr_t *kv, *v; - - kv = isccc_alist_assq(alist, key); - if (kv != NULL) { - v = ISCCC_SEXPR_CDR(kv); - if (isccc_sexpr_binaryp(v)) { - if (strp != NULL) - *strp = isccc_sexpr_tostring(v); - return (ISC_R_SUCCESS); - } else - return (ISC_R_EXISTS); - } - - return (ISC_R_NOTFOUND); -} - -isc_result_t -isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key, - isc_uint32_t *uintp) -{ - isccc_sexpr_t *kv, *v; - - kv = isccc_alist_assq(alist, key); - if (kv != NULL) { - v = ISCCC_SEXPR_CDR(kv); - if (isccc_sexpr_binaryp(v)) { - if (uintp != NULL) - *uintp = (isc_uint32_t) - strtoul(isccc_sexpr_tostring(v), - NULL, 10); - return (ISC_R_SUCCESS); - } else - return (ISC_R_EXISTS); - } - - return (ISC_R_NOTFOUND); -} - -static void -symtab_undefine(char *key, unsigned int type, isccc_symvalue_t value, - void *arg) -{ - UNUSED(type); - UNUSED(value); - UNUSED(arg); - - free(key); -} - -static isc_boolean_t -symtab_clean(char *key, unsigned int type, isccc_symvalue_t value, - void *arg) -{ - isccc_time_t *now; - - UNUSED(key); - UNUSED(type); - - now = arg; - - if (*now < value.as_uinteger) - return (ISC_FALSE); - if ((*now - value.as_uinteger) < DUP_LIFETIME) - return (ISC_FALSE); - return (ISC_TRUE); -} - -isc_result_t -isccc_cc_createsymtab(isccc_symtab_t **symtabp) -{ - return (isccc_symtab_create(11897, symtab_undefine, NULL, ISC_FALSE, - symtabp)); -} - -void -isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now) -{ - isccc_symtab_foreach(symtab, symtab_clean, &now); -} - -static isc_boolean_t -has_whitespace(const char *str) -{ - char c; - - if (str == NULL) - return (ISC_FALSE); - while ((c = *str++) != '\0') { - if (c == ' ' || c == '\t' || c == '\n') - return (ISC_TRUE); - } - return (ISC_FALSE); -} - -isc_result_t -isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message, - isccc_time_t now) -{ - const char *_frm; - const char *_to; - char *_ser, *_tim, *tmp; - isc_result_t result; - char *key; - size_t len; - isccc_symvalue_t value; - isccc_sexpr_t *_ctrl; - - _ctrl = isccc_alist_lookup(message, "_ctrl"); - if (_ctrl == NULL || - isccc_cc_lookupstring(_ctrl, "_ser", &_ser) != ISC_R_SUCCESS || - isccc_cc_lookupstring(_ctrl, "_tim", &_tim) != ISC_R_SUCCESS) - return (ISC_R_FAILURE); - /* - * _frm and _to are optional. - */ - if (isccc_cc_lookupstring(_ctrl, "_frm", &tmp) != ISC_R_SUCCESS) - _frm = ""; - else - _frm = tmp; - if (isccc_cc_lookupstring(_ctrl, "_to", &tmp) != ISC_R_SUCCESS) - _to = ""; - else - _to = tmp; - /* - * Ensure there is no newline in any of the strings. This is so - * we can write them to a file later. - */ - if (has_whitespace(_frm) || has_whitespace(_to) || - has_whitespace(_ser) || has_whitespace(_tim)) - return (ISC_R_FAILURE); - len = strlen(_frm) + strlen(_to) + strlen(_ser) + strlen(_tim) + 4; - key = malloc(len); - if (key == NULL) - return (ISC_R_NOMEMORY); - snprintf(key, len, "%s;%s;%s;%s", _frm, _to, _ser, _tim); - value.as_uinteger = now; - result = isccc_symtab_define(symtab, key, ISCCC_SYMTYPE_CCDUP, value, - isccc_symexists_reject); - if (result != ISC_R_SUCCESS) { - free(key); - return (result); - } - - return (ISC_R_SUCCESS); -} |