diff options
author | Othmar Gsenger <otti@anytun.org> | 2007-12-27 11:13:13 +0000 |
---|---|---|
committer | Othmar Gsenger <otti@anytun.org> | 2007-12-27 11:13:13 +0000 |
commit | 6dc4f1912caf7f01f4b977ff8aaa50be61db2aba (patch) | |
tree | d7a281c430052e04156265d9ab3108c631360a5e /keyexchange/isakmpd-20041012/policy.c | |
parent | removed old isakmpd (diff) |
adden new isakmpd
Diffstat (limited to 'keyexchange/isakmpd-20041012/policy.c')
-rw-r--r-- | keyexchange/isakmpd-20041012/policy.c | 2318 |
1 files changed, 2318 insertions, 0 deletions
diff --git a/keyexchange/isakmpd-20041012/policy.c b/keyexchange/isakmpd-20041012/policy.c new file mode 100644 index 0000000..279b3a1 --- /dev/null +++ b/keyexchange/isakmpd-20041012/policy.c @@ -0,0 +1,2318 @@ +/* $OpenBSD: policy.c,v 1.78 2004/08/08 19:11:06 deraadt Exp $ */ +/* $EOM: policy.c,v 1.49 2000/10/24 13:33:39 niklas Exp $ */ + +/* + * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis. All rights reserved. + * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code was written under funding by Ericsson Radio Systems. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/queue.h> +#include <sys/stat.h> +#include <regex.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <keynote.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <openssl/ssl.h> +#include <netdb.h> + +#include "sysdep.h" + +#include "conf.h" +#include "exchange.h" +#include "ipsec.h" +#include "isakmp_doi.h" +#include "sa.h" +#include "transport.h" +#include "log.h" +#include "message.h" +#include "monitor.h" +#include "util.h" +#include "policy.h" +#include "x509.h" + +char **policy_asserts = NULL; +int ignore_policy = 0; +int policy_asserts_num = 0; +struct exchange *policy_exchange = 0; +struct sa *policy_sa = 0; +struct sa *policy_isakmp_sa = 0; + +static const char hextab[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +/* + * Adaptation of Vixie's inet_ntop4 () + */ +static const char * +my_inet_ntop4(const in_addr_t *src, char *dst, size_t size, int normalize) +{ + static const char fmt[] = "%03u.%03u.%03u.%03u"; + char tmp[sizeof "255.255.255.255"]; + in_addr_t src2; + + if (normalize) + src2 = ntohl(*src); + else + src2 = *src; + + if (snprintf(tmp, sizeof tmp, fmt, ((u_int8_t *)&src2)[0], + ((u_int8_t *)&src2)[1], ((u_int8_t *)&src2)[2], + ((u_int8_t *)&src2)[3]) > (int)size) { + errno = ENOSPC; + return 0; + } + strlcpy(dst, tmp, size); + return dst; +} + +static const char * +my_inet_ntop6(const unsigned char *src, char *dst, size_t size) +{ + static const char fmt[] = + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"; + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; + + if (snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3], + src[4], src[5], src[6], src[7], src[8], src[9], src[10], src[11], + src[12], src[13], src[14], src[15]) > (int)size) { + errno = ENOSPC; + return 0; + } + strlcpy(dst, tmp, size); + return dst; +} + +char * +policy_callback(char *name) +{ + struct proto *proto; + + u_int8_t *attr, *value, *id, *idlocal, *idremote; + size_t id_sz, idlocalsz, idremotesz; + struct sockaddr *sin; + struct ipsec_exch *ie; + struct ipsec_sa *is; + size_t i; + int fmt, lifetype = 0; + in_addr_t net, subnet; + u_int16_t len, type; + time_t tt; + char *addr; + static char mytimeofday[15]; + + /* We use all these as a cache. */ +#define PMAX 32 + static char *esp_present, *ah_present, *comp_present; + static char *ah_hash_alg, *ah_auth_alg, *esp_auth_alg, *esp_enc_alg; + static char *comp_alg, ah_life_kbytes[PMAX], ah_life_seconds[PMAX]; + static char esp_life_kbytes[PMAX], esp_life_seconds[PMAX]; + static char comp_life_kbytes[PMAX]; + static char *ah_ecn, *esp_ecn, *comp_ecn; + static char comp_life_seconds[PMAX], *ah_encapsulation; + static char *esp_encapsulation, *comp_encapsulation; + static char ah_key_length[PMAX], esp_key_length[PMAX]; + static char ah_key_rounds[PMAX], esp_key_rounds[PMAX]; + static char comp_dict_size[PMAX], comp_private_alg[PMAX]; + static char *remote_filter_type, *local_filter_type; + static char remote_filter_addr_upper[NI_MAXHOST]; + static char remote_filter_addr_lower[NI_MAXHOST]; + static char local_filter_addr_upper[NI_MAXHOST]; + static char local_filter_addr_lower[NI_MAXHOST]; + static char ah_group_desc[PMAX], esp_group_desc[PMAX]; + static char comp_group_desc[PMAX], remote_ike_address[NI_MAXHOST]; + static char local_ike_address[NI_MAXHOST]; + static char *remote_id_type, remote_id_addr_upper[NI_MAXHOST]; + static char *phase_1, remote_id_addr_lower[NI_MAXHOST]; + static char *remote_id_proto, remote_id_port[PMAX]; + static char remote_filter_port[PMAX], local_filter_port[PMAX]; + static char *remote_filter_proto, *local_filter_proto, *pfs; + static char *initiator, remote_filter_proto_num[3]; + static char local_filter_proto_num[3], remote_id_proto_num[3]; + static char phase1_group[PMAX]; + + /* Allocated. */ + static char *remote_filter = 0, *local_filter = 0, *remote_id = 0; + + static int dirty = 1; + + /* We only need to set dirty at initialization time really. */ + if (strcmp(name, KEYNOTE_CALLBACK_CLEANUP) == 0 + || strcmp(name, KEYNOTE_CALLBACK_INITIALIZE) == 0) { + esp_present = ah_present = comp_present = pfs = "no"; + ah_hash_alg = ah_auth_alg = phase_1 = ""; + esp_auth_alg = esp_enc_alg = comp_alg = ah_encapsulation = ""; + ah_ecn = esp_ecn = comp_ecn = "no"; + esp_encapsulation = comp_encapsulation = ""; + remote_filter_type = ""; + local_filter_type = remote_id_type = initiator = ""; + remote_filter_proto = local_filter_proto = ""; + remote_id_proto = ""; + + if (remote_filter != 0) { + free(remote_filter); + remote_filter = 0; + } + if (local_filter != 0) { + free(local_filter); + local_filter = 0; + } + if (remote_id != 0) { + free(remote_id); + remote_id = 0; + } + memset(remote_ike_address, 0, sizeof remote_ike_address); + memset(local_ike_address, 0, sizeof local_ike_address); + memset(ah_life_kbytes, 0, sizeof ah_life_kbytes); + memset(ah_life_seconds, 0, sizeof ah_life_seconds); + memset(esp_life_kbytes, 0, sizeof esp_life_kbytes); + memset(esp_life_seconds, 0, sizeof esp_life_seconds); + memset(comp_life_kbytes, 0, sizeof comp_life_kbytes); + memset(comp_life_seconds, 0, sizeof comp_life_seconds); + memset(ah_key_length, 0, sizeof ah_key_length); + memset(ah_key_rounds, 0, sizeof ah_key_rounds); + memset(esp_key_length, 0, sizeof esp_key_length); + memset(esp_key_rounds, 0, sizeof esp_key_rounds); + memset(comp_dict_size, 0, sizeof comp_dict_size); + memset(comp_private_alg, 0, sizeof comp_private_alg); + memset(remote_filter_addr_upper, 0, + sizeof remote_filter_addr_upper); + memset(remote_filter_addr_lower, 0, + sizeof remote_filter_addr_lower); + memset(local_filter_addr_upper, 0, + sizeof local_filter_addr_upper); + memset(local_filter_addr_lower, 0, + sizeof local_filter_addr_lower); + memset(remote_id_addr_upper, 0, sizeof remote_id_addr_upper); + memset(remote_id_addr_lower, 0, sizeof remote_id_addr_lower); + memset(ah_group_desc, 0, sizeof ah_group_desc); + memset(esp_group_desc, 0, sizeof esp_group_desc); + memset(remote_id_port, 0, sizeof remote_id_port); + memset(remote_filter_port, 0, sizeof remote_filter_port); + memset(local_filter_port, 0, sizeof local_filter_port); + memset(phase1_group, 0, sizeof phase1_group); + + dirty = 1; + return ""; + } + /* + * If dirty is set, this is the first request for an attribute, so + * populate our value cache. + */ + if (dirty) { + ie = policy_exchange->data; + + if (ie->pfs) + pfs = "yes"; + + is = policy_isakmp_sa->data; + snprintf(phase1_group, sizeof phase1_group, "%u", + is->group_desc); + + for (proto = TAILQ_FIRST(&policy_sa->protos); proto; + proto = TAILQ_NEXT(proto, link)) { + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_present = "yes"; + switch (proto->id) { + case IPSEC_AH_MD5: + ah_hash_alg = "md5"; + break; + + case IPSEC_AH_SHA: + ah_hash_alg = "sha"; + break; + + case IPSEC_AH_RIPEMD: + ah_hash_alg = "ripemd"; + break; + + case IPSEC_AH_SHA2_256: + ah_auth_alg = "sha2-256"; + break; + + case IPSEC_AH_SHA2_384: + ah_auth_alg = "sha2-384"; + break; + + case IPSEC_AH_SHA2_512: + ah_auth_alg = "sha2-512"; + break; + + case IPSEC_AH_DES: + ah_hash_alg = "des"; + break; + } + + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_present = "yes"; + switch (proto->id) { + case IPSEC_ESP_DES_IV64: + esp_enc_alg = "des-iv64"; + break; + + case IPSEC_ESP_DES: + esp_enc_alg = "des"; + break; + + case IPSEC_ESP_3DES: + esp_enc_alg = "3des"; + break; + + case IPSEC_ESP_AES: + case IPSEC_ESP_AES_128_CTR: + esp_enc_alg = "aes"; + break; + + case IPSEC_ESP_RC5: + esp_enc_alg = "rc5"; + break; + + case IPSEC_ESP_IDEA: + esp_enc_alg = "idea"; + break; + + case IPSEC_ESP_CAST: + esp_enc_alg = "cast"; + break; + + case IPSEC_ESP_BLOWFISH: + esp_enc_alg = "blowfish"; + break; + + case IPSEC_ESP_3IDEA: + esp_enc_alg = "3idea"; + break; + + case IPSEC_ESP_DES_IV32: + esp_enc_alg = "des-iv32"; + break; + + case IPSEC_ESP_RC4: + esp_enc_alg = "rc4"; + break; + + case IPSEC_ESP_NULL: + esp_enc_alg = "null"; + break; + } + + break; + + case IPSEC_PROTO_IPCOMP: + comp_present = "yes"; + switch (proto->id) { + case IPSEC_IPCOMP_OUI: + comp_alg = "oui"; + break; + + case IPSEC_IPCOMP_DEFLATE: + comp_alg = "deflate"; + break; + + case IPSEC_IPCOMP_LZS: + comp_alg = "lzs"; + break; + + case IPSEC_IPCOMP_V42BIS: + comp_alg = "v42bis"; + break; + } + + break; + } + + for (attr = proto->chosen->p + + ISAKMP_TRANSFORM_SA_ATTRS_OFF; + attr < proto->chosen->p + + GET_ISAKMP_GEN_LENGTH(proto->chosen->p); + attr = value + len) { + if (attr + ISAKMP_ATTR_VALUE_OFF > + (proto->chosen->p + + GET_ISAKMP_GEN_LENGTH(proto->chosen->p))) + return ""; + + type = GET_ISAKMP_ATTR_TYPE(attr); + fmt = ISAKMP_ATTR_FORMAT(type); + type = ISAKMP_ATTR_TYPE(type); + value = attr + (fmt ? + ISAKMP_ATTR_LENGTH_VALUE_OFF : + ISAKMP_ATTR_VALUE_OFF); + len = (fmt ? ISAKMP_ATTR_LENGTH_VALUE_LEN : + GET_ISAKMP_ATTR_LENGTH_VALUE(attr)); + + if (value + len > proto->chosen->p + + GET_ISAKMP_GEN_LENGTH(proto->chosen->p)) + return ""; + + switch (type) { + case IPSEC_ATTR_SA_LIFE_TYPE: + lifetype = decode_16(value); + break; + + case IPSEC_ATTR_SA_LIFE_DURATION: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + if (lifetype == IPSEC_DURATION_SECONDS) { + if (len == 2) + snprintf(ah_life_seconds, sizeof ah_life_seconds, + "%u", decode_16(value)); + else + snprintf(ah_life_seconds, sizeof ah_life_seconds, + "%u", decode_32(value)); + } else { + if (len == 2) + snprintf(ah_life_kbytes, sizeof ah_life_kbytes, + "%u", decode_16(value)); + else + snprintf(ah_life_kbytes, sizeof ah_life_kbytes, + "%u", decode_32(value)); + } + + break; + + case IPSEC_PROTO_IPSEC_ESP: + if (lifetype == IPSEC_DURATION_SECONDS) { + if (len == 2) + snprintf(esp_life_seconds, + sizeof esp_life_seconds, "%u", + decode_16(value)); + else + snprintf(esp_life_seconds, + sizeof esp_life_seconds, "%u", + decode_32(value)); + } else { + if (len == 2) + snprintf(esp_life_kbytes, + sizeof esp_life_kbytes, "%u", + decode_16(value)); + else + snprintf(esp_life_kbytes, + sizeof esp_life_kbytes, "%u", + decode_32(value)); + } + + break; + + case IPSEC_PROTO_IPCOMP: + if (lifetype == IPSEC_DURATION_SECONDS) { + if (len == 2) + snprintf(comp_life_seconds, + sizeof comp_life_seconds, "%u", + decode_16(value)); + else + snprintf(comp_life_seconds, + sizeof comp_life_seconds, "%u", + decode_32(value)); + } else { + if (len == 2) + snprintf(comp_life_kbytes, + sizeof comp_life_kbytes, "%u", + decode_16(value)); + else + snprintf(comp_life_kbytes, + sizeof comp_life_kbytes, "%u", + decode_32(value)); + } + break; + } + break; + + case IPSEC_ATTR_GROUP_DESCRIPTION: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + snprintf(ah_group_desc, + sizeof ah_group_desc, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPSEC_ESP: + snprintf(esp_group_desc, + sizeof esp_group_desc, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPCOMP: + snprintf(comp_group_desc, + sizeof comp_group_desc, "%u", + decode_16(value)); + break; + } + break; + + case IPSEC_ATTR_ECN_TUNNEL: + if (decode_16(value)) + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_ecn = "yes"; + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_ecn = "yes"; + break; + + case IPSEC_PROTO_IPCOMP: + comp_ecn = "yes"; + break; + } + + case IPSEC_ATTR_ENCAPSULATION_MODE: + if (decode_16(value) == IPSEC_ENCAP_TUNNEL) + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_encapsulation = "tunnel"; + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_encapsulation = "tunnel"; + break; + + case IPSEC_PROTO_IPCOMP: + comp_encapsulation = "tunnel"; + break; + } +#if defined (USE_NAT_TRAVERSAL) + else if (decode_16(value) == + IPSEC_ENCAP_UDP_ENCAP_TUNNEL || + decode_16(value) == + IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT) + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_encapsulation = "udp-encap-tunnel"; + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_encapsulation = "udp-encap-tunnel"; + break; + + case IPSEC_PROTO_IPCOMP: + comp_encapsulation = "udp-encap-tunnel"; + break; + } + /* XXX IPSEC_ENCAP_UDP_ENCAP_TRANSPORT */ +#endif + else + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + ah_encapsulation = "transport"; + break; + + case IPSEC_PROTO_IPSEC_ESP: + esp_encapsulation = "transport"; + break; + + case IPSEC_PROTO_IPCOMP: + comp_encapsulation = "transport"; + break; + } + break; + + case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + switch (decode_16(value)) { + case IPSEC_AUTH_HMAC_MD5: + ah_auth_alg = "hmac-md5"; + break; + + case IPSEC_AUTH_HMAC_SHA: + ah_auth_alg = "hmac-sha"; + break; + + case IPSEC_AUTH_HMAC_RIPEMD: + ah_auth_alg = "hmac-ripemd"; + break; + + case IPSEC_AUTH_HMAC_SHA2_256: + ah_auth_alg = "hmac-sha2-256"; + break; + + case IPSEC_AUTH_HMAC_SHA2_384: + ah_auth_alg = "hmac-sha2-384"; + break; + + case IPSEC_AUTH_HMAC_SHA2_512: + ah_auth_alg = "hmac-sha2-512"; + break; + + case IPSEC_AUTH_DES_MAC: + ah_auth_alg = "des-mac"; + break; + + case IPSEC_AUTH_KPDK: + ah_auth_alg = "kpdk"; + break; + } + break; + + case IPSEC_PROTO_IPSEC_ESP: + switch (decode_16(value)) { + case IPSEC_AUTH_HMAC_MD5: + esp_auth_alg = "hmac-md5"; + break; + + case IPSEC_AUTH_HMAC_SHA: + esp_auth_alg = "hmac-sha"; + break; + + case IPSEC_AUTH_HMAC_RIPEMD: + esp_auth_alg = "hmac-ripemd"; + break; + + case IPSEC_AUTH_HMAC_SHA2_256: + esp_auth_alg = "hmac-sha2-256"; + break; + + case IPSEC_AUTH_HMAC_SHA2_384: + esp_auth_alg = "hmac-sha2-384"; + break; + + case IPSEC_AUTH_HMAC_SHA2_512: + esp_auth_alg = "hmac-sha2-512"; + break; + + case IPSEC_AUTH_DES_MAC: + esp_auth_alg = "des-mac"; + break; + + case IPSEC_AUTH_KPDK: + esp_auth_alg = "kpdk"; + break; + } + break; + } + break; + + case IPSEC_ATTR_KEY_LENGTH: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + snprintf(ah_key_length, + sizeof ah_key_length, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPSEC_ESP: + snprintf(esp_key_length, + sizeof esp_key_length, "%u", + decode_16(value)); + break; + } + break; + + case IPSEC_ATTR_KEY_ROUNDS: + switch (proto->proto) { + case IPSEC_PROTO_IPSEC_AH: + snprintf(ah_key_rounds, + sizeof ah_key_rounds, "%u", + decode_16(value)); + break; + + case IPSEC_PROTO_IPSEC_ESP: + snprintf(esp_key_rounds, + sizeof esp_key_rounds, "%u", + decode_16(value)); + break; + } + break; + + case IPSEC_ATTR_COMPRESS_DICTIONARY_SIZE: + snprintf(comp_dict_size, + sizeof comp_dict_size, "%u", + decode_16(value)); + break; + + case IPSEC_ATTR_COMPRESS_PRIVATE_ALGORITHM: + snprintf(comp_private_alg, + sizeof comp_private_alg, "%u", + decode_16(value)); + break; + } + } + } + + policy_sa->transport->vtbl->get_src(policy_sa->transport, + &sin); + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: sockaddr2text failed"); + goto bad; + } + strlcpy(local_ike_address, addr, sizeof local_ike_address); + free(addr); + + policy_sa->transport->vtbl->get_dst(policy_sa->transport, + &sin); + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: sockaddr2text failed"); + goto bad; + } + strlcpy(remote_ike_address, addr, sizeof remote_ike_address); + free(addr); + + switch (policy_isakmp_sa->exch_type) { + case ISAKMP_EXCH_AGGRESSIVE: + phase_1 = "aggressive"; + break; + + case ISAKMP_EXCH_ID_PROT: + phase_1 = "main"; + break; + } + + if (policy_isakmp_sa->initiator) { + id = policy_isakmp_sa->id_r; + id_sz = policy_isakmp_sa->id_r_len; + } else { + id = policy_isakmp_sa->id_i; + id_sz = policy_isakmp_sa->id_i_len; + } + + switch (id[0]) { + case IPSEC_ID_IPV4_ADDR: + remote_id_type = "IPv4 address"; + + net = decode_32(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ); + my_inet_ntop4(&net, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1, 1); + my_inet_ntop4(&net, remote_id_addr_lower, + sizeof remote_id_addr_lower - 1, 1); + remote_id = strdup(remote_id_addr_upper); + if (!remote_id) { + log_error("policy_callback: " + "strdup (\"%s\") failed", + remote_id_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV4_RANGE: + remote_id_type = "IPv4 range"; + + net = decode_32(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ); + my_inet_ntop4(&net, remote_id_addr_lower, + sizeof remote_id_addr_lower - 1, 1); + net = decode_32(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ + 4); + my_inet_ntop4(&net, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1, 1); + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); + break; + + case IPSEC_ID_IPV4_ADDR_SUBNET: + remote_id_type = "IPv4 subnet"; + + net = decode_32(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ); + subnet = decode_32(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ + 4); + net &= subnet; + my_inet_ntop4(&net, remote_id_addr_lower, + sizeof remote_id_addr_lower - 1, 1); + net |= ~subnet; + my_inet_ntop4(&net, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1, 1); + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR: + remote_id_type = "IPv6 address"; + my_inet_ntop6(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + remote_id_addr_upper, sizeof remote_id_addr_upper); + strlcpy(remote_id_addr_lower, remote_id_addr_upper, + sizeof remote_id_addr_lower); + remote_id = strdup(remote_id_addr_upper); + if (!remote_id) { + log_error("policy_callback: " + "strdup (\"%s\") failed", + remote_id_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV6_RANGE: + remote_id_type = "IPv6 range"; + + my_inet_ntop6(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + remote_id_addr_lower, + sizeof remote_id_addr_lower - 1); + + my_inet_ntop6(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ + 16, remote_id_addr_upper, + sizeof remote_id_addr_upper - 1); + + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + { + struct in6_addr net, mask; + + remote_id_type = "IPv6 subnet"; + + bcopy(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, &net, + sizeof(net)); + bcopy(id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ + 16, + &mask, sizeof(mask)); + + for (i = 0; i < 16; i++) + net.s6_addr[i] &= mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *)&net, + remote_id_addr_lower, + sizeof remote_id_addr_lower - 1); + + for (i = 0; i < 16; i++) + net.s6_addr[i] |= ~mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *)&net, + remote_id_addr_upper, + sizeof remote_id_addr_upper - 1); + + len = strlen(remote_id_addr_upper) + + strlen(remote_id_addr_lower) + 2; + remote_id = calloc(len, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_id, remote_id_addr_lower, len); + strlcat(remote_id, "-", len); + strlcat(remote_id, remote_id_addr_upper, len); + break; + } + + case IPSEC_ID_FQDN: + remote_id_type = "FQDN"; + remote_id = calloc(id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: " + "calloc (%lu, %lu) failed", + (unsigned long)id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, + (unsigned long)sizeof(char)); + goto bad; + } + memcpy(remote_id, + id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + break; + + case IPSEC_ID_USER_FQDN: + remote_id_type = "User FQDN"; + remote_id = calloc(id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: " + "calloc (%lu, %lu) failed", + (unsigned long)id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, + (unsigned long)sizeof(char)); + goto bad; + } + memcpy(remote_id, + id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + break; + + case IPSEC_ID_DER_ASN1_DN: + remote_id_type = "ASN1 DN"; + + remote_id = x509_DN_string(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + if (!remote_id) { + LOG_DBG((LOG_POLICY, 50, + "policy_callback: failed to decode name")); + goto bad; + } + break; + + case IPSEC_ID_DER_ASN1_GN: /* XXX */ + remote_id_type = "ASN1 GN"; + break; + + case IPSEC_ID_KEY_ID: + remote_id_type = "Key ID"; + remote_id = calloc(2 * (id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ) + 1, sizeof(char)); + if (!remote_id) { + log_error("policy_callback: " + "calloc (%lu, %lu) failed", + 2 * ((unsigned long)id_sz - + ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ) + 1, + (unsigned long)sizeof(char)); + goto bad; + } + /* Does it contain any non-printable characters ? */ + for (i = 0; + i < id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; + i++) + if (!isprint(*(id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ + i))) + break; + if (i >= id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ) { + memcpy(remote_id, id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ, + id_sz - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ); + break; + } + /* Non-printable characters, convert to hex */ + for (i = 0; + i < id_sz - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ; + i++) { + remote_id[2 * i] = hextab[*(id + + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ) >> 4]; + remote_id[2 * i + 1] = hextab[*(id + + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ) & 0xF]; + } + break; + + default: + log_print("policy_callback: " + "unknown remote ID type %u", id[0]); + goto bad; + } + + switch (id[1]) { + case IPPROTO_TCP: + remote_id_proto = "tcp"; + break; + + case IPPROTO_UDP: + remote_id_proto = "udp"; + break; + +#ifdef IPPROTO_ETHERIP + case IPPROTO_ETHERIP: + remote_id_proto = "etherip"; + break; +#endif + + default: + snprintf(remote_id_proto_num, + sizeof remote_id_proto_num, "%d", + id[1]); + remote_id_proto = remote_id_proto_num; + break; + } + + snprintf(remote_id_port, sizeof remote_id_port, "%u", + decode_16(id + 2)); + + if (policy_exchange->initiator) { + initiator = "yes"; + idlocal = ie->id_ci; + idremote = ie->id_cr; + idlocalsz = ie->id_ci_sz; + idremotesz = ie->id_cr_sz; + } else { + initiator = "no"; + idlocal = ie->id_cr; + idremote = ie->id_ci; + idlocalsz = ie->id_cr_sz; + idremotesz = ie->id_ci_sz; + } + + /* Initialize the ID variables. */ + if (idremote) { + switch (GET_ISAKMP_ID_TYPE(idremote)) { + case IPSEC_ID_IPV4_ADDR: + remote_filter_type = "IPv4 address"; + + net = decode_32(idremote + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1, 1); + my_inet_ntop4(&net, remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1, 1); + remote_filter = + strdup(remote_filter_addr_upper); + if (!remote_filter) { + log_error("policy_callback: strdup " + "(\"%s\") failed", + remote_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV4_RANGE: + remote_filter_type = "IPv4 range"; + + net = decode_32(idremote + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1, 1); + net = decode_32(idremote + ISAKMP_ID_DATA_OFF + + 4); + my_inet_ntop4(&net, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1, 1); + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc " + "(%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_filter, + remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, + remote_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV4_ADDR_SUBNET: + remote_filter_type = "IPv4 subnet"; + + net = decode_32(idremote + ISAKMP_ID_DATA_OFF); + subnet = decode_32(idremote + + ISAKMP_ID_DATA_OFF + 4); + net &= subnet; + my_inet_ntop4(&net, remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1, 1); + net |= ~subnet; + my_inet_ntop4(&net, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1, 1); + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc " + "(%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_filter, + remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, + remote_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR: + remote_filter_type = "IPv6 address"; + my_inet_ntop6(idremote + ISAKMP_ID_DATA_OFF, + remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1); + strlcpy(remote_filter_addr_lower, + remote_filter_addr_upper, + sizeof remote_filter_addr_lower); + remote_filter = + strdup(remote_filter_addr_upper); + if (!remote_filter) { + log_error("policy_callback: strdup " + "(\"%s\") failed", + remote_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV6_RANGE: + remote_filter_type = "IPv6 range"; + + my_inet_ntop6(idremote + ISAKMP_ID_DATA_OFF, + remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1); + + my_inet_ntop6(idremote + ISAKMP_ID_DATA_OFF + + 16, remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1); + + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: calloc " + "(%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_filter, + remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, + remote_filter_addr_upper, len); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + { + struct in6_addr net, mask; + + remote_filter_type = "IPv6 subnet"; + + bcopy(idremote + ISAKMP_ID_DATA_OFF, + &net, sizeof(net)); + bcopy(idremote + ISAKMP_ID_DATA_OFF + + 16, &mask, sizeof(mask)); + + for (i = 0; i < 16; i++) + net.s6_addr[i] &= + mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *)&net, + remote_filter_addr_lower, + sizeof remote_filter_addr_lower - 1); + + for (i = 0; i < 16; i++) + net.s6_addr[i] |= + ~mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *)&net, + remote_filter_addr_upper, + sizeof remote_filter_addr_upper - 1); + + len = strlen(remote_filter_addr_upper) + + strlen(remote_filter_addr_lower) + 2; + remote_filter = calloc(len, + sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", + len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(remote_filter, + remote_filter_addr_lower, len); + strlcat(remote_filter, "-", len); + strlcat(remote_filter, + remote_filter_addr_upper, len); + break; + } + + case IPSEC_ID_FQDN: + remote_filter_type = "FQDN"; + remote_filter = malloc(idremotesz - + ISAKMP_ID_DATA_OFF + 1); + if (!remote_filter) { + log_error("policy_callback: " + "malloc (%lu) failed", + (unsigned long)idremotesz - + ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(remote_filter, + idremote + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + remote_filter[idremotesz - ISAKMP_ID_DATA_OFF] + = '\0'; + break; + + case IPSEC_ID_USER_FQDN: + remote_filter_type = "User FQDN"; + remote_filter = malloc(idremotesz - + ISAKMP_ID_DATA_OFF + 1); + if (!remote_filter) { + log_error("policy_callback: " + "malloc (%lu) failed", + (unsigned long)idremotesz - + ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(remote_filter, + idremote + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + remote_filter[idremotesz - ISAKMP_ID_DATA_OFF] + = '\0'; + break; + + case IPSEC_ID_DER_ASN1_DN: + remote_filter_type = "ASN1 DN"; + + remote_filter = x509_DN_string(idremote + + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + if (!remote_filter) { + LOG_DBG((LOG_POLICY, 50, + "policy_callback: " + "failed to decode name")); + goto bad; + } + break; + + case IPSEC_ID_DER_ASN1_GN: /* XXX -- not sure + * what's in this. */ + remote_filter_type = "ASN1 GN"; + break; + + case IPSEC_ID_KEY_ID: + remote_filter_type = "Key ID"; + remote_filter + = calloc(2 * (idremotesz - + ISAKMP_ID_DATA_OFF) + 1, + sizeof(char)); + if (!remote_filter) { + log_error("policy_callback: " + "calloc (%lu, %lu) failed", + 2 * ((unsigned long)idremotesz - + ISAKMP_ID_DATA_OFF) + 1, + (unsigned long)sizeof(char)); + goto bad; + } + /* + * Does it contain any non-printable + * characters ? + */ + for (i = 0; + i < idremotesz - ISAKMP_ID_DATA_OFF; i++) + if (!isprint(*(idremote + + ISAKMP_ID_DATA_OFF + i))) + break; + if (i >= idremotesz - ISAKMP_ID_DATA_OFF) { + memcpy(remote_filter, + idremote + ISAKMP_ID_DATA_OFF, + idremotesz - ISAKMP_ID_DATA_OFF); + break; + } + /* Non-printable characters, convert to hex */ + for (i = 0; + i < idremotesz - ISAKMP_ID_DATA_OFF; + i++) { + remote_filter[2 * i] + = hextab[*(idremote + + ISAKMP_ID_DATA_OFF) >> 4]; + remote_filter[2 * i + 1] + = hextab[*(idremote + + ISAKMP_ID_DATA_OFF) & 0xF]; + } + break; + + default: + log_print("policy_callback: " + "unknown Remote ID type %u", + GET_ISAKMP_ID_TYPE(idremote)); + goto bad; + } + + switch (idremote[ISAKMP_GEN_SZ + 1]) { + case IPPROTO_TCP: + remote_filter_proto = "tcp"; + break; + + case IPPROTO_UDP: + remote_filter_proto = "udp"; + break; + +#ifdef IPPROTO_ETHERIP + case IPPROTO_ETHERIP: + remote_filter_proto = "etherip"; + break; +#endif + + default: + snprintf(remote_filter_proto_num, + sizeof remote_filter_proto_num, "%d", + idremote[ISAKMP_GEN_SZ + 1]); + remote_filter_proto = remote_filter_proto_num; + break; + } + + snprintf(remote_filter_port, sizeof remote_filter_port, + "%u", decode_16(idremote + ISAKMP_GEN_SZ + 2)); + } else { + policy_sa->transport->vtbl->get_dst(policy_sa->transport, &sin); + switch (sin->sa_family) { + case AF_INET: + remote_filter_type = "IPv4 address"; + break; + case AF_INET6: + remote_filter_type = "IPv6 address"; + break; + default: + log_print("policy_callback: " + "unsupported protocol family %d", + sin->sa_family); + goto bad; + } + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: " + "sockaddr2text failed"); + goto bad; + } + memcpy(remote_filter_addr_upper, addr, + sizeof remote_filter_addr_upper); + memcpy(remote_filter_addr_lower, addr, + sizeof remote_filter_addr_lower); + free(addr); + remote_filter = strdup(remote_filter_addr_upper); + if (!remote_filter) { + log_error("policy_callback: " + "strdup (\"%s\") failed", + remote_filter_addr_upper); + goto bad; + } + } + + if (idlocal) { + switch (GET_ISAKMP_ID_TYPE(idlocal)) { + case IPSEC_ID_IPV4_ADDR: + local_filter_type = "IPv4 address"; + + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1, 1); + my_inet_ntop4(&net, local_filter_addr_lower, + sizeof local_filter_addr_upper - 1, 1); + local_filter = strdup(local_filter_addr_upper); + if (!local_filter) { + log_error("policy_callback: " + "strdup (\"%s\") failed", + local_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV4_RANGE: + local_filter_type = "IPv4 range"; + + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF); + my_inet_ntop4(&net, local_filter_addr_lower, + sizeof local_filter_addr_lower - 1, 1); + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF + + 4); + my_inet_ntop4(&net, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1, 1); + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + 2; + local_filter = calloc(len, sizeof(char)); + if (!local_filter) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(local_filter, local_filter_addr_lower, + len); + strlcat(local_filter, "-", len); + strlcat(local_filter, local_filter_addr_upper, + len); + break; + + case IPSEC_ID_IPV4_ADDR_SUBNET: + local_filter_type = "IPv4 subnet"; + + net = decode_32(idlocal + ISAKMP_ID_DATA_OFF); + subnet = decode_32(idlocal + + ISAKMP_ID_DATA_OFF + 4); + net &= subnet; + my_inet_ntop4(&net, local_filter_addr_lower, + sizeof local_filter_addr_lower - 1, 1); + net |= ~subnet; + my_inet_ntop4(&net, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1, 1); + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + 2; + local_filter = calloc(len, sizeof(char)); + if (!local_filter) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(local_filter, local_filter_addr_lower, + len); + strlcat(local_filter, "-", len); + strlcat(local_filter, local_filter_addr_upper, + len); + break; + + case IPSEC_ID_IPV6_ADDR: + local_filter_type = "IPv6 address"; + my_inet_ntop6(idlocal + ISAKMP_ID_DATA_OFF, + local_filter_addr_upper, + sizeof local_filter_addr_upper - 1); + strlcpy(local_filter_addr_lower, + local_filter_addr_upper, + sizeof local_filter_addr_lower); + local_filter = strdup(local_filter_addr_upper); + if (!local_filter) { + log_error("policy_callback: " + "strdup (\"%s\") failed", + local_filter_addr_upper); + goto bad; + } + break; + + case IPSEC_ID_IPV6_RANGE: + local_filter_type = "IPv6 range"; + + my_inet_ntop6(idlocal + ISAKMP_ID_DATA_OFF, + local_filter_addr_lower, + sizeof local_filter_addr_lower - 1); + + my_inet_ntop6(idlocal + ISAKMP_ID_DATA_OFF + + 16, local_filter_addr_upper, + sizeof local_filter_addr_upper - 1); + + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + 2; + local_filter = calloc(len, sizeof(char)); + if (!local_filter) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(local_filter, local_filter_addr_lower, + len); + strlcat(local_filter, "-", len); + strlcat(local_filter, local_filter_addr_upper, + len); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + { + struct in6_addr net, mask; + + local_filter_type = "IPv6 subnet"; + + bcopy(idlocal + ISAKMP_ID_DATA_OFF, + &net, sizeof(net)); + bcopy(idlocal + ISAKMP_ID_DATA_OFF + + 16, &mask, sizeof(mask)); + + for (i = 0; i < 16; i++) + net.s6_addr[i] &= + mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *)&net, + local_filter_addr_lower, + sizeof local_filter_addr_lower - 1); + + for (i = 0; i < 16; i++) + net.s6_addr[i] |= + ~mask.s6_addr[i]; + + my_inet_ntop6((unsigned char *)&net, + local_filter_addr_upper, + sizeof local_filter_addr_upper - + 1); + + len = strlen(local_filter_addr_upper) + + strlen(local_filter_addr_lower) + + 2; + local_filter = calloc(len, + sizeof(char)); + if (!local_filter) { + log_error("policy_callback: " + "calloc (%d, %lu) failed", + len, + (unsigned long)sizeof(char)); + goto bad; + } + strlcpy(local_filter, + local_filter_addr_lower, len); + strlcat(local_filter, "-", len); + strlcat(local_filter, + local_filter_addr_upper, len); + break; + } + + case IPSEC_ID_FQDN: + local_filter_type = "FQDN"; + local_filter = malloc(idlocalsz - + ISAKMP_ID_DATA_OFF + 1); + if (!local_filter) { + log_error("policy_callback: " + "malloc (%lu) failed", + (unsigned long)idlocalsz - + ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(local_filter, + idlocal + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + local_filter[idlocalsz - ISAKMP_ID_DATA_OFF] + = '\0'; + break; + + case IPSEC_ID_USER_FQDN: + local_filter_type = "User FQDN"; + local_filter = malloc(idlocalsz - + ISAKMP_ID_DATA_OFF + 1); + if (!local_filter) { + log_error("policy_callback: " + "malloc (%lu) failed", + (unsigned long)idlocalsz - + ISAKMP_ID_DATA_OFF + 1); + goto bad; + } + memcpy(local_filter, + idlocal + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + local_filter[idlocalsz - ISAKMP_ID_DATA_OFF] + = '\0'; + break; + + case IPSEC_ID_DER_ASN1_DN: + local_filter_type = "ASN1 DN"; + + local_filter = x509_DN_string(idlocal + + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + if (!local_filter) { + LOG_DBG((LOG_POLICY, 50, + "policy_callback: failed to decode" + " name")); + goto bad; + } + break; + + case IPSEC_ID_DER_ASN1_GN: + /* XXX -- not sure what's in this. */ + local_filter_type = "ASN1 GN"; + break; + + case IPSEC_ID_KEY_ID: + local_filter_type = "Key ID"; + local_filter = calloc(2 * (idlocalsz - + ISAKMP_ID_DATA_OFF) + 1, + sizeof(char)); + if (!local_filter) { + log_error("policy_callback: " + "calloc (%lu, %lu) failed", + 2 * ((unsigned long)idlocalsz - + ISAKMP_ID_DATA_OFF) + 1, + (unsigned long)sizeof(char)); + goto bad; + } + /* + * Does it contain any non-printable + * characters ? + */ + for (i = 0; + i < idlocalsz - ISAKMP_ID_DATA_OFF; i++) + if (!isprint(*(idlocal + + ISAKMP_ID_DATA_OFF + i))) + break; + if (i >= idlocalsz - ISAKMP_ID_DATA_OFF) { + memcpy(local_filter, idlocal + + ISAKMP_ID_DATA_OFF, + idlocalsz - ISAKMP_ID_DATA_OFF); + break; + } + /* Non-printable characters, convert to hex */ + for (i = 0; + i < idlocalsz - ISAKMP_ID_DATA_OFF; i++) { + local_filter[2 * i] + = hextab[*(idlocal + + ISAKMP_ID_DATA_OFF) >> 4]; + local_filter[2 * i + 1] + = hextab[*(idlocal + + ISAKMP_ID_DATA_OFF) & 0xF]; + } + break; + + default: + log_print("policy_callback: " + "unknown Local ID type %u", + GET_ISAKMP_ID_TYPE(idlocal)); + goto bad; + } + + switch (idlocal[ISAKMP_GEN_SZ + 1]) { + case IPPROTO_TCP: + local_filter_proto = "tcp"; + break; + + case IPPROTO_UDP: + local_filter_proto = "udp"; + break; + +#ifdef IPPROTO_ETHERIP + case IPPROTO_ETHERIP: + local_filter_proto = "etherip"; + break; +#endif + + default: + snprintf(local_filter_proto_num, + sizeof local_filter_proto_num, + "%d", idlocal[ISAKMP_GEN_SZ + 1]); + local_filter_proto = local_filter_proto_num; + break; + } + + snprintf(local_filter_port, sizeof local_filter_port, + "%u", decode_16(idlocal + ISAKMP_GEN_SZ + 2)); + } else { + policy_sa->transport->vtbl->get_src(policy_sa->transport, + (struct sockaddr **)&sin); + switch (sin->sa_family) { + case AF_INET: + local_filter_type = "IPv4 address"; + break; + case AF_INET6: + local_filter_type = "IPv6 address"; + break; + default: + log_print("policy_callback: " + "unsupported protocol family %d", + sin->sa_family); + goto bad; + } + + if (sockaddr2text(sin, &addr, 1)) { + log_error("policy_callback: " + "sockaddr2text failed"); + goto bad; + } + memcpy(local_filter_addr_upper, addr, + sizeof local_filter_addr_upper); + memcpy(local_filter_addr_lower, addr, + sizeof local_filter_addr_lower); + free(addr); + local_filter = strdup(local_filter_addr_upper); + if (!local_filter) { + log_error("policy_callback: " + "strdup (\"%s\") failed", + local_filter_addr_upper); + goto bad; + } + } + + LOG_DBG((LOG_POLICY, 80, + "Policy context (action attributes):")); + LOG_DBG((LOG_POLICY, 80, "esp_present == %s", esp_present)); + LOG_DBG((LOG_POLICY, 80, "ah_present == %s", ah_present)); + LOG_DBG((LOG_POLICY, 80, "comp_present == %s", comp_present)); + LOG_DBG((LOG_POLICY, 80, "ah_hash_alg == %s", ah_hash_alg)); + LOG_DBG((LOG_POLICY, 80, "esp_enc_alg == %s", esp_enc_alg)); + LOG_DBG((LOG_POLICY, 80, "comp_alg == %s", comp_alg)); + LOG_DBG((LOG_POLICY, 80, "ah_auth_alg == %s", ah_auth_alg)); + LOG_DBG((LOG_POLICY, 80, "esp_auth_alg == %s", esp_auth_alg)); + LOG_DBG((LOG_POLICY, 80, "ah_life_seconds == %s", + ah_life_seconds)); + LOG_DBG((LOG_POLICY, 80, "ah_life_kbytes == %s", + ah_life_kbytes)); + LOG_DBG((LOG_POLICY, 80, "esp_life_seconds == %s", + esp_life_seconds)); + LOG_DBG((LOG_POLICY, 80, "esp_life_kbytes == %s", + esp_life_kbytes)); + LOG_DBG((LOG_POLICY, 80, "comp_life_seconds == %s", + comp_life_seconds)); + LOG_DBG((LOG_POLICY, 80, "comp_life_kbytes == %s", + comp_life_kbytes)); + LOG_DBG((LOG_POLICY, 80, "ah_encapsulation == %s", + ah_encapsulation)); + LOG_DBG((LOG_POLICY, 80, "esp_encapsulation == %s", + esp_encapsulation)); + LOG_DBG((LOG_POLICY, 80, "comp_encapsulation == %s", + comp_encapsulation)); + LOG_DBG((LOG_POLICY, 80, "comp_dict_size == %s", + comp_dict_size)); + LOG_DBG((LOG_POLICY, 80, "comp_private_alg == %s", + comp_private_alg)); + LOG_DBG((LOG_POLICY, 80, "ah_key_length == %s", + ah_key_length)); + LOG_DBG((LOG_POLICY, 80, "ah_key_rounds == %s", + ah_key_rounds)); + LOG_DBG((LOG_POLICY, 80, "esp_key_length == %s", + esp_key_length)); + LOG_DBG((LOG_POLICY, 80, "esp_key_rounds == %s", + esp_key_rounds)); + LOG_DBG((LOG_POLICY, 80, "ah_group_desc == %s", + ah_group_desc)); + LOG_DBG((LOG_POLICY, 80, "esp_group_desc == %s", + esp_group_desc)); + LOG_DBG((LOG_POLICY, 80, "comp_group_desc == %s", + comp_group_desc)); + LOG_DBG((LOG_POLICY, 80, "ah_ecn == %s", ah_ecn)); + LOG_DBG((LOG_POLICY, 80, "esp_ecn == %s", esp_ecn)); + LOG_DBG((LOG_POLICY, 80, "comp_ecn == %s", comp_ecn)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_type == %s", + remote_filter_type)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_addr_upper == %s", + remote_filter_addr_upper)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_addr_lower == %s", + remote_filter_addr_lower)); + LOG_DBG((LOG_POLICY, 80, "remote_filter == %s", + (remote_filter ? remote_filter : ""))); + LOG_DBG((LOG_POLICY, 80, "remote_filter_port == %s", + remote_filter_port)); + LOG_DBG((LOG_POLICY, 80, "remote_filter_proto == %s", + remote_filter_proto)); + LOG_DBG((LOG_POLICY, 80, "local_filter_type == %s", + local_filter_type)); + LOG_DBG((LOG_POLICY, 80, "local_filter_addr_upper == %s", + local_filter_addr_upper)); + LOG_DBG((LOG_POLICY, 80, "local_filter_addr_lower == %s", + local_filter_addr_lower)); + LOG_DBG((LOG_POLICY, 80, "local_filter == %s", + (local_filter ? local_filter : ""))); + LOG_DBG((LOG_POLICY, 80, "local_filter_port == %s", + local_filter_port)); + LOG_DBG((LOG_POLICY, 80, "local_filter_proto == %s", + local_filter_proto)); + LOG_DBG((LOG_POLICY, 80, "remote_id_type == %s", + remote_id_type)); + LOG_DBG((LOG_POLICY, 80, "remote_id_addr_upper == %s", + remote_id_addr_upper)); + LOG_DBG((LOG_POLICY, 80, "remote_id_addr_lower == %s", + remote_id_addr_lower)); + LOG_DBG((LOG_POLICY, 80, "remote_id == %s", + (remote_id ? remote_id : ""))); + LOG_DBG((LOG_POLICY, 80, "remote_id_port == %s", + remote_id_port)); + LOG_DBG((LOG_POLICY, 80, "remote_id_proto == %s", + remote_id_proto)); + LOG_DBG((LOG_POLICY, 80, "remote_negotiation_address == %s", + remote_ike_address)); + LOG_DBG((LOG_POLICY, 80, "local_negotiation_address == %s", + local_ike_address)); + LOG_DBG((LOG_POLICY, 80, "pfs == %s", pfs)); + LOG_DBG((LOG_POLICY, 80, "initiator == %s", initiator)); + LOG_DBG((LOG_POLICY, 80, "phase1_group_desc == %s", + phase1_group)); + + /* Unset dirty now. */ + dirty = 0; + } + if (strcmp(name, "phase_1") == 0) + return phase_1; + + if (strcmp(name, "GMTTimeOfDay") == 0) { + tt = time((time_t)NULL); + strftime(mytimeofday, 14, "%Y%m%d%H%M%S", gmtime(&tt)); + return mytimeofday; + } + if (strcmp(name, "LocalTimeOfDay") == 0) { + tt = time((time_t)NULL); + strftime(mytimeofday, 14, "%Y%m%d%H%M%S", localtime(&tt)); + return mytimeofday; + } + if (strcmp(name, "initiator") == 0) + return initiator; + + if (strcmp(name, "pfs") == 0) + return pfs; + + if (strcmp(name, "app_domain") == 0) + return "IPsec policy"; + + if (strcmp(name, "doi") == 0) + return "ipsec"; + + if (strcmp(name, "esp_present") == 0) + return esp_present; + + if (strcmp(name, "ah_present") == 0) + return ah_present; + + if (strcmp(name, "comp_present") == 0) + return comp_present; + + if (strcmp(name, "ah_hash_alg") == 0) + return ah_hash_alg; + + if (strcmp(name, "ah_auth_alg") == 0) + return ah_auth_alg; + + if (strcmp(name, "esp_auth_alg") == 0) + return esp_auth_alg; + + if (strcmp(name, "esp_enc_alg") == 0) + return esp_enc_alg; + + if (strcmp(name, "comp_alg") == 0) + return comp_alg; + + if (strcmp(name, "ah_life_kbytes") == 0) + return ah_life_kbytes; + + if (strcmp(name, "ah_life_seconds") == 0) + return ah_life_seconds; + + if (strcmp(name, "esp_life_kbytes") == 0) + return esp_life_kbytes; + + if (strcmp(name, "esp_life_seconds") == 0) + return esp_life_seconds; + + if (strcmp(name, "comp_life_kbytes") == 0) + return comp_life_kbytes; + + if (strcmp(name, "comp_life_seconds") == 0) + return comp_life_seconds; + + if (strcmp(name, "ah_encapsulation") == 0) + return ah_encapsulation; + + if (strcmp(name, "esp_encapsulation") == 0) + return esp_encapsulation; + + if (strcmp(name, "comp_encapsulation") == 0) + return comp_encapsulation; + + if (strcmp(name, "ah_key_length") == 0) + return ah_key_length; + + if (strcmp(name, "ah_key_rounds") == 0) + return ah_key_rounds; + + if (strcmp(name, "esp_key_length") == 0) + return esp_key_length; + + if (strcmp(name, "esp_key_rounds") == 0) + return esp_key_rounds; + + if (strcmp(name, "comp_dict_size") == 0) + return comp_dict_size; + + if (strcmp(name, "comp_private_alg") == 0) + return comp_private_alg; + + if (strcmp(name, "remote_filter_type") == 0) + return remote_filter_type; + + if (strcmp(name, "remote_filter") == 0) + return (remote_filter ? remote_filter : ""); + + if (strcmp(name, "remote_filter_addr_upper") == 0) + return remote_filter_addr_upper; + + if (strcmp(name, "remote_filter_addr_lower") == 0) + return remote_filter_addr_lower; + + if (strcmp(name, "remote_filter_port") == 0) + return remote_filter_port; + + if (strcmp(name, "remote_filter_proto") == 0) + return remote_filter_proto; + + if (strcmp(name, "local_filter_type") == 0) + return local_filter_type; + + if (strcmp(name, "local_filter") == 0) + return (local_filter ? local_filter : ""); + + if (strcmp(name, "local_filter_addr_upper") == 0) + return local_filter_addr_upper; + + if (strcmp(name, "local_filter_addr_lower") == 0) + return local_filter_addr_lower; + + if (strcmp(name, "local_filter_port") == 0) + return local_filter_port; + + if (strcmp(name, "local_filter_proto") == 0) + return local_filter_proto; + + if (strcmp(name, "remote_ike_address") == 0) + return remote_ike_address; + + if (strcmp(name, "remote_negotiation_address") == 0) + return remote_ike_address; + + if (strcmp(name, "local_ike_address") == 0) + return local_ike_address; + + if (strcmp(name, "local_negotiation_address") == 0) + return local_ike_address; + + if (strcmp(name, "remote_id_type") == 0) + return remote_id_type; + + if (strcmp(name, "remote_id") == 0) + return (remote_id ? remote_id : ""); + + if (strcmp(name, "remote_id_addr_upper") == 0) + return remote_id_addr_upper; + + if (strcmp(name, "remote_id_addr_lower") == 0) + return remote_id_addr_lower; + + if (strcmp(name, "remote_id_port") == 0) + return remote_id_port; + + if (strcmp(name, "remote_id_proto") == 0) + return remote_id_proto; + + if (strcmp(name, "phase1_group_desc") == 0) + return phase1_group; + + if (strcmp(name, "esp_group_desc") == 0) + return esp_group_desc; + + if (strcmp(name, "ah_group_desc") == 0) + return ah_group_desc; + + if (strcmp(name, "comp_group_desc") == 0) + return comp_group_desc; + + if (strcmp(name, "comp_ecn") == 0) + return comp_ecn; + + if (strcmp(name, "ah_ecn") == 0) + return ah_ecn; + + if (strcmp(name, "esp_ecn") == 0) + return esp_ecn; + + return ""; + +bad: + policy_callback(KEYNOTE_CALLBACK_INITIALIZE); + return ""; +} + +void +policy_init(void) +{ + char *ptr, *policy_file, *use_keynote; + char **asserts; + size_t sz, len; + int fd, i; + + LOG_DBG((LOG_POLICY, 30, "policy_init: initializing")); + + /* Do we want to use the policy modules? */ + use_keynote = conf_get_str("General", "Use-Keynote"); + if (ignore_policy || + (use_keynote && strncmp("yes", use_keynote, 3))) + return; + + /* Get policy file from configuration. */ + policy_file = conf_get_str("General", "Policy-file"); + if (!policy_file) + policy_file = CONF_DFLT_POLICY_FILE; + + /* Open policy file. */ + fd = monitor_open(policy_file, O_RDONLY, 0); + if (fd == -1) + log_fatal("policy_init: open (\"%s\", O_RDONLY) failed", + policy_file); + + /* Check file modes and collect file size */ + if (check_file_secrecy_fd(fd, policy_file, &sz)) { + close(fd); + log_fatal("policy_init: cannot read %s", policy_file); + } + + /* Allocate memory to keep policies. */ + ptr = calloc(sz + 1, sizeof(char)); + if (!ptr) + log_fatal("policy_init: calloc (%lu, %lu) failed", + (unsigned long)sz + 1, (unsigned long)sizeof(char)); + + /* Just in case there are short reads... */ + for (len = 0; len < sz; len += i) { + i = read(fd, ptr + len, sz - len); + if (i == -1) + log_fatal("policy_init: read (%d, %p, %lu) failed", fd, + ptr + len, (unsigned long)(sz - len)); + } + + /* We're done with this. */ + close(fd); + + /* Parse buffer, break up into individual policies. */ + asserts = kn_read_asserts(ptr, sz, &i); + + /* Begone! */ + free(ptr); + + if (asserts == (char **)NULL) + log_print("policy_init: all policies flushed"); + + /* Cleanup */ + if (policy_asserts) { + for (fd = 0; fd < policy_asserts_num; fd++) + if (policy_asserts && policy_asserts[fd]) + free(policy_asserts[fd]); + + free(policy_asserts); + } + policy_asserts = asserts; + policy_asserts_num = i; +} + +/* Nothing needed for initialization */ +int +keynote_cert_init(void) +{ + return 1; +} + +/* Just copy and return. */ +void * +keynote_cert_get(u_int8_t *data, u_int32_t len) +{ + char *foo = malloc(len + 1); + + if (foo == NULL) + return NULL; + + memcpy(foo, data, len); + foo[len] = '\0'; + return foo; +} + +/* + * We just verify the signature on the credentials. + * On signature failure, just drop the whole payload. + */ +int +keynote_cert_validate(void *scert) +{ + char **foo; + int num, i; + + if (scert == NULL) + return 0; + + foo = kn_read_asserts((char *)scert, strlen((char *)scert), &num); + if (foo == NULL) + return 0; + + for (i = 0; i < num; i++) { + if (kn_verify_assertion(scert, strlen((char *)scert)) + != SIGRESULT_TRUE) { + for (; i < num; i++) + free(foo[i]); + free(foo); + return 0; + } + free(foo[i]); + } + + free(foo); + return 1; +} + +/* Add received credentials. */ +int +keynote_cert_insert(int sid, void *scert) +{ + char **foo; + int num; + + if (scert == NULL) + return 0; + + foo = kn_read_asserts((char *)scert, strlen((char *)scert), &num); + if (foo == NULL) + return 0; + + while (num--) + kn_add_assertion(sid, foo[num], strlen(foo[num]), 0); + + return 1; +} + +/* Just regular memory free. */ +void +keynote_cert_free(void *cert) +{ + free(cert); +} + +/* Verify that the key given to us is valid. */ +int +keynote_certreq_validate(u_int8_t *data, u_int32_t len) +{ + struct keynote_deckey dc; + int err = 1; + char *dat; + + dat = calloc(len + 1, sizeof(char)); + if (!dat) { + log_error("keynote_certreq_validate: calloc (%d, %lu) failed", + len + 1, (unsigned long)sizeof(char)); + return 0; + } + memcpy(dat, data, len); + + if (kn_decode_key(&dc, dat, KEYNOTE_PUBLIC_KEY) != 0) + err = 0; + else + kn_free_key(&dc); + + free(dat); + + return err; +} + +/* Beats me what we should be doing with this. */ +void * +keynote_certreq_decode(u_int8_t *data, u_int32_t len) +{ + /* XXX */ + return NULL; +} + +void +keynote_free_aca(void *blob) +{ + /* XXX */ +} + +int +keynote_cert_obtain(u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, + u_int32_t *certlen) +{ + char *dirname, *file, *addr_str; + struct stat sb; + size_t size; + int idtype, fd, len; + + if (!id) { + log_print("keynote_cert_obtain: ID is missing"); + return 0; + } + /* Get type of ID. */ + idtype = id[0]; + id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + + dirname = conf_get_str("KeyNote", "Credential-directory"); + if (!dirname) { + LOG_DBG((LOG_POLICY, 30, + "keynote_cert_obtain: no Credential-directory")); + return 0; + } + len = strlen(dirname) + strlen(CREDENTIAL_FILE) + 3; + + switch (idtype) { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + util_ntoa(&addr_str, idtype == IPSEC_ID_IPV4_ADDR ? + AF_INET : AF_INET6, id); + if (addr_str == 0) + return 0; + + file = calloc(len + strlen(addr_str), sizeof(char)); + if (file == NULL) { + log_error("keynote_cert_obtain: failed to allocate " + "%lu bytes", (unsigned long)len + + strlen(addr_str)); + free(addr_str); + return 0; + } + snprintf(file, len + strlen(addr_str), "%s/%s/%s", dirname, + addr_str, CREDENTIAL_FILE); + free(addr_str); + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: { + file = calloc(len + id_len, sizeof(char)); + if (file == NULL) { + log_error("keynote_cert_obtain: " + "failed to allocate %lu bytes", + (unsigned long)len + id_len); + return 0; + } + snprintf(file, len + id_len, "%s/", dirname); + memcpy(file + strlen(dirname) + 1, id, id_len); + snprintf(file + strlen(dirname) + 1 + id_len, + len - strlen(dirname) - 1, "/%s", CREDENTIAL_FILE); + break; + } + + default: + return 0; + } + + fd = monitor_open(file, O_RDONLY, 0); + if (fd < 0) { + LOG_DBG((LOG_POLICY, 30, "keynote_cert_obtain: " + "failed to open \"%s\"", file)); + free(file); + return 0; + } + + if (fstat(fd, &sb) < 0) { + LOG_DBG((LOG_POLICY, 30, "keynote_cert_obtain: " + "failed to stat \"%s\"", file)); + free(file); + close(fd); + return 0; + } + size = (size_t)sb.st_size; + + *cert = calloc(size + 1, sizeof(char)); + if (*cert == NULL) { + log_error("keynote_cert_obtain: failed to allocate %lu bytes", + (unsigned long)size); + free(file); + return 0; + } + + if (read(fd, *cert, size) != (int)size) { + LOG_DBG((LOG_POLICY, 30, "keynote_cert_obtain: " + "failed to read %lu bytes from \"%s\"", + (unsigned long)size, file)); + free(file); + close(fd); + return 0; + } + close(fd); + free(file); + *certlen = size; + return 1; +} + +/* This should never be called. */ +int +keynote_cert_get_subjects(void *scert, int *n, u_int8_t ***id, + u_int32_t **id_len) +{ + return 0; +} + +/* Get the authorizer key. */ +int +keynote_cert_get_key(void *scert, void *keyp) +{ + struct keynote_keylist *kl; + int sid, kid, num; + char **foo; + + foo = kn_read_asserts((char *)scert, strlen((char *)scert), &num); + if (foo == NULL || num == 0) { + log_print("keynote_cert_get_key: " + "failed to decompose credentials"); + return 0; + } + kid = kn_init(); + if (kid == -1) { + log_print("keynote_cert_get_key: " + "failed to initialize new policy session"); + while (num--) + free(foo[num]); + free(foo); + return 0; + } + sid = kn_add_assertion(kid, foo[num - 1], strlen(foo[num - 1]), 0); + while (num--) + free(foo[num]); + free(foo); + + if (sid == -1) { + log_print("keynote_cert_get_key: failed to add assertion"); + kn_close(kid); + return 0; + } + *(RSA **)keyp = NULL; + + kl = kn_get_licensees(kid, sid); + while (kl) { + if (kl->key_alg == KEYNOTE_ALGORITHM_RSA || + kl->key_alg == KEYNOTE_ALGORITHM_X509) { + *(RSA **)keyp = RSAPublicKey_dup(kl->key_key); + break; + } + kl = kl->key_next; + } + + kn_remove_assertion(kid, sid); + kn_close(kid); + return *(RSA **)keyp == NULL ? 0 : 1; +} + +void * +keynote_cert_dup(void *cert) +{ + return strdup((char *)cert); +} + +void +keynote_serialize(void *cert, u_int8_t **data, u_int32_t *datalen) +{ + *datalen = strlen((char *)cert) + 1; + *data = (u_int8_t *)strdup(cert); /* i.e an extra character at + * the end... */ + if (*data == NULL) + log_error("keynote_serialize: malloc (%d) failed", *datalen); +} + +/* From cert to printable */ +char * +keynote_printable(void *cert) +{ + return strdup((char *)cert); +} + +/* From printable to cert */ +void * +keynote_from_printable(char *cert) +{ + return strdup(cert); +} |