/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_configuration_file.c,v $ $Revision: 1.23.10.10 $ * $Source: /home/interpeak/CVSRoot/ipike/src/ipike_configuration_file.c,v $ * $Author: jsheng $ $Date: 2013-04-28 08:58:41 $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipike_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #include "ipike_h.h" #include "ipike_configuration.h" #include "ipike_configuration_api.h" #include "ipike_configuration_file.h" #include "ipike_configuration_parse.h" #include "ipike_crypto.h" #include "ipike_util.h" #include #include #include /* **************************************************************************** * 4 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 5 DEFINES **************************************************************************** */ #define INVALID_LEN (Ip_size_t)(-1) #define IPIKE_SA_LIFE_TIME_DEFAULT "8 hours" /* **************************************************************************** * 6 TYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipike_config_parse_proposal *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_proposal( Ipike_config* config, Ipike_config_api_proposal*** proposals) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* entry = IP_NULL; Ipike_config_api_proposal* proposal = IP_NULL; if (IP_NULL == (proposal = ipcom_calloc(1, sizeof(*proposal)))) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; } while ((IPIKE_SUCCESS == err) && (entry = ipike_configuration_enum(config, entry))) { if (ipcom_strcasecmp(entry->name, "dh_group") == 0) { err = ipike_parse_string(entry->value, &proposal->dh_group); } else if (ipcom_strcasecmp(entry->name, "hash_algorithm") == 0) { err = ipike_parse_string(entry->value, &proposal->hash_alg); } else if (ipcom_strcasecmp(entry->name, "encryption_algorithm") == 0) { err = ipike_parse_string(entry->value, &proposal->encryption_alg); } else if (ipcom_strcasecmp(entry->name, "integrity_algorithm") == 0) { err = ipike_parse_string(entry->value, &proposal->integrity_alg); } else if (ipcom_strcasecmp(entry->name, "use_esn") == 0) { err = ipike_parse_string(entry->value, &proposal->use_esn); } else if (ipcom_strcasecmp(entry->name, "v1_lifetime") == 0) { err = ipike_parse_string(entry->value, &proposal->v1.lifetime); } else if (ipcom_strcasecmp(entry->name, "number") == 0) { err = ipike_parse_string(entry->value, &proposal->number); } else { IPCOM_LOG2(INFO, "Unknown '%s' entry for '%s', ignored...", entry->name, config->name); } if (IPIKE_CONF_INVALID_VALUE == err) IPCOM_LOG3(ERR, "Invalid value '%s' for '%s' at '%s'", entry->value, entry->name, config->name); } if (IPIKE_SUCCESS == err) { ipike_to_lower_string((char*)proposal->dh_group); ipike_to_lower_string((char*)proposal->hash_alg); ipike_to_lower_string((char*)proposal->encryption_alg); ipike_to_lower_string((char*)proposal->integrity_alg); ipike_to_lower_string((char*)proposal->use_esn); err = ipike_array_add((void***)proposals, proposal); } if (IPIKE_SUCCESS != err) ipcom_free(proposal); return err; } /* *=========================================================================== * ipike_config_free_proposal *=========================================================================== */ IP_STATIC void ipike_config_free_proposal(Ipike_config_api_proposal* proposal) { ipike_config_api_release_proposal(proposal); ipcom_free(proposal); } /* *=========================================================================== * ipike_config_free_proposals *=========================================================================== */ IP_STATIC void ipike_config_free_proposals(Ipike_config_api_proposal*** proposals) { ipike_array_free((void**)*proposals, (void(*)(void*))ipike_config_free_proposal); *proposals = IP_NULL; } /* *=========================================================================== * ipike_config_free_rohc *=========================================================================== */ IP_STATIC void ipike_config_free_rohc(Ipike_config_api_rohc ** rohc) { ip_assert(rohc != IP_NULL); if ( *rohc == IP_NULL ) return; ipike_parse_delete_string((*rohc)->max_cid); ipike_parse_delete_string((*rohc)->mrru); ipike_parse_delete_string((*rohc)->profiles); ipike_parse_delete_string((*rohc)->icv_len); ipike_parse_delete_string((*rohc)->integrity_alg); ipcom_free(*rohc); *rohc = IP_NULL; } /* *=========================================================================== * ipike_config_parse_authentication *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_authentication( Ipike_config* config, Ipike_config_api_ike_sa* ike_sa) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* entry = IP_NULL; while ((IPIKE_SUCCESS == err) && (entry = ipike_configuration_enum(config, entry))) { if (ipcom_strcasecmp(entry->name, "method") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.method); } else if (ipcom_strcasecmp(entry->name, "psk_id") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.psk_id); } else if (ipcom_strcasecmp(entry->name, "shared_key") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.shared_key); } else if (ipcom_strcasecmp(entry->name, "certificate") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.certificate); } else if (ipcom_strcasecmp(entry->name, "send_certificate") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.send_certificate); } else if (ipcom_strcasecmp(entry->name, "request_certificate") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.request_certificate); } else if (ipcom_strcasecmp(entry->name, "ocsp_response") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.ocsp_response); } else if (ipcom_strcasecmp(entry->name, "remote_certificate") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.remote_certificate); } else if (ipcom_strcasecmp(entry->name, "key_id") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.key_id); } else if (ipcom_strcasecmp(entry->name, "private_key") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.private_key); } else if (ipcom_strcasecmp(entry->name, "private_key_password") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.private_key_password); } else if (ipcom_strcasecmp(entry->name, "trusted_ca_store") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.trusted_ca_store); } else if (ipcom_strcasecmp(entry->name, "crl_store") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.crl_store); } else if (ipcom_strcasecmp(entry->name, "intermediate_ca_store") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.intermediate_ca_store); } else if (ipcom_strcasecmp(entry->name, "identity") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.identity); } else if (ipcom_strcasecmp(entry->name, "certificate_uri") == 0) { err = ipike_parse_string(entry->value, &ike_sa->authentication.certificate_uri); } else { IPCOM_LOG2(INFO, "Unknown '%s' entry for '%s', ignored...", entry->name, config->name); } if (IPIKE_CONF_INVALID_VALUE == err) IPCOM_LOG3(ERR, "Invalid value '%s' for '%s' at '%s'", entry->value, entry->name, config->name); } return err; } /* *=========================================================================== * ipike_config_parse_radius *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_radius( Ipike_config* config, Ipike_config_api_ike_sa* ike_sa) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* entry = IP_NULL; while ((IPIKE_SUCCESS == err) && (entry = ipike_configuration_enum(config, entry))) { if (ipcom_strcasecmp(entry->name, "shared_secret") == 0) { err = ipike_parse_string(entry->value, &ike_sa->radius.shared_secret); } else if (ipcom_strcasecmp(entry->name, "server_address") == 0) { err = ipike_parse_string(entry->value, &ike_sa->radius.server_address); } else if (ipcom_strcasecmp(entry->name, "local_address") == 0) { err = ipike_parse_string(entry->value, &ike_sa->radius.local_address); } else { IPCOM_LOG2(INFO, "Unknown '%s' entry for '%s', ignored...", entry->name, config->name); } if (IPIKE_CONF_INVALID_VALUE == err) IPCOM_LOG3(ERR, "Invalid value '%s' for '%s' at '%s'", entry->value, entry->name, config->name); } return err; } /* *=========================================================================== * ipike_config_parse_ike_sa *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_ike_sa( Ipike_config* config, Ipike_config_api_ike_sa* sa, Ipike_config_api_proposal*** proposals, char** ike_id) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* entry = IP_NULL; Ip_u32 u_val = 0; if (*config->value != 0) err = ipike_parse_string(config->value, &sa->remote_address); if (IPIKE_SUCCESS != err) { IPCOM_LOG1(ERR, "Invalid address for '%s'", config->name); } err = ipike_parse_string(IPIKE_SA_LIFE_TIME_DEFAULT, &sa->lifetime); while ((IPIKE_SUCCESS == err) && (entry = ipike_configuration_enum(config, entry))) { if (ipcom_strcasecmp(entry->name, "ike_id") == 0) { if (IP_NULL != ike_id) err = ipike_parse_string(entry->value, (const char**)ike_id); } else if (ipcom_strcasecmp(entry->name, "exchange_version") == 0) { err = ipike_parse_string(entry->value, &sa->version); } else if (ipcom_strcasecmp(entry->name, "exchange_mode") == 0) { err = ipike_parse_string(entry->value, &sa->mode); } else if (ipcom_strcasecmp(entry->name, "local_address") == 0) { err = ipike_parse_string(entry->value, &sa->local_address); } else if (ipcom_strcasecmp(entry->name, "passive") == 0) { err = ipike_parse_bool(entry->value, &sa->passive); } else if (ipcom_strcasecmp(entry->name, "initial_contact") == 0) { err = ipike_parse_bool(entry->value, &sa->initial_contact); } else if (ipcom_strcasecmp(entry->name, "reauth") == 0) { err = ipike_parse_bool(entry->value, &sa->reauth); } else if (ipcom_strcasecmp(entry->name, "liveness") == 0) { err = ipike_parse_number(entry->value, &u_val); sa->liveness = (Ip_s32)u_val; } else if (ipcom_strcasecmp(entry->name, "local_identifier") == 0) { err = ipike_parse_string(entry->value, &sa->local_id); } else if (ipcom_strcasecmp(entry->name, "remote_identifier") == 0) { err = ipike_parse_string(entry->value, &sa->remote_id); } else if (ipcom_strcasecmp(entry->name, "lifetime") == 0) { err = ipike_parse_string(entry->value, &sa->lifetime); } else if (ipcom_strcasecmp(entry->name, "proposal") == 0) { err = ipike_config_parse_proposal(entry, proposals); } else if (ipcom_strcasecmp(entry->name, "authentication") == 0) { err = ipike_config_parse_authentication(entry, sa); } else if (ipcom_strcasecmp(entry->name, "radius") == 0) { err = ipike_config_parse_radius(entry, sa); } else { IPCOM_LOG2(INFO, "Unknown '%s' entry for '%s', ignored...", entry->name, config->name); } if (IPIKE_CONF_INVALID_VALUE == err) IPCOM_LOG3(ERR, "Invalid value '%s' for '%s' at '%s'", entry->value, entry->name, config->name); } return err; } /* *=========================================================================== * ipike_config_free_ike_sa *=========================================================================== */ IP_STATIC void ipike_config_free_ike_sa(Ipike_config_api_ike_sa* sa) { ipike_config_api_release_ike_sa(sa); return; } /* *=========================================================================== * ipike_config_parse_flow *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_flow(Ipike_config* config, Ipike_config_api_ipsec_sa* sa) { Ipike_error err = IPIKE_SUCCESS; Ip_bool pos = 0; const char* psz; char* psz2, *tmp; /* Format: address [] address [] [] */ /* or range format. Masks should be ignored if ranges are used! */ /* Format: address - [-] address - [-] [] */ psz = config->value; while ((IPIKE_SUCCESS == err) && (*psz != 0) && (ipike_parse_get_string(&psz, ' ', &psz2) == 0)) { pos++; if ((ipcom_strcasecmp(psz2, "address") == 0) || (ipcom_strcasecmp(psz2, "network") == 0)) { if (pos == 3) /* src port not specified */ pos++; } else if ((ipcom_strncasecmp(psz2,"any", 3) == 0) || (ipcom_strncasecmp(psz2,"icmpv6", 6) == 0) || (ipcom_strncasecmp(psz2,"icmp", 4) == 0) || (ipcom_strncasecmp(psz2,"udp", 3) == 0) || (ipcom_strncasecmp(psz2,"tcp",3) == 0) || (ipcom_strncmp(psz2, "0x", 2) == 0)) { err = ipike_parse_string(psz2, &sa->flow.protocol); } else if (pos == 2) { /* Address/port Range support */ tmp = psz2; /* Copy orig pointer */ err = ipike_parse_string(psz2, &sa->flow.src_address); psz2 = tmp; /* Reset ptr */ } else if (pos == 3) { tmp = psz2; /* Copy orig pointer */ err = ipike_parse_string(psz2, &sa->flow.src_port); psz2 = tmp; /* Reset ptr */ } else if (pos == 5) { tmp = psz2; /* Copy orig pointer */ err = ipike_parse_string(psz2, &sa->flow.dst_address); psz2 = tmp; /* Reset ptr */ } else if (pos == 6) { tmp = psz2; /* Copy orig pointer */ err = ipike_parse_string(psz2, &sa->flow.dst_port); psz2 = tmp; /* Reset ptr */ } else { IPCOM_LOG2(ERR, "Invalid flow parameter '%s' for '%s'", psz2, config->name); } ipcom_free(psz2); } return err; } /* *=========================================================================== * ipike_config_parse_rohc *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_rohc( Ipike_config* config, Ipike_config_api_rohc** rohc) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* entry = IP_NULL; Ipike_config_api_rohc* r = IP_NULL; r = ipcom_calloc(1, sizeof(Ipike_config_api_rohc)); if ( r == IP_NULL ) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; goto errout; } while ( (entry = ipike_configuration_enum(config, entry)) ) { if (ipcom_strcasecmp(entry->name, "max_cid") == 0) err = ipike_parse_string(entry->value, &r->max_cid); else if (ipcom_strcasecmp(entry->name, "profiles") == 0) err = ipike_parse_string(entry->value, &r->profiles); else if (ipcom_strcasecmp(entry->name, "mrru") == 0) err = ipike_parse_string(entry->value, &r->mrru); else if (ipcom_strcasecmp(entry->name, "integrity_algorithm") == 0) err = ipike_parse_string(entry->value, &r->integrity_alg); else if (ipcom_strcasecmp(entry->name, "icv_len") == 0) err = ipike_parse_string(entry->value, &r->icv_len); else IPCOM_LOG2(INFO, "Unknown '%s' entry for '%s', ignored...", entry->name, config->name); if (err != IPIKE_SUCCESS) { IPCOM_LOG3(ERR, "Invalid value '%s' for '%s' at '%s'", entry->value, entry->name, config->name); goto errout; } } ipike_to_lower_string((char*)r->max_cid); ipike_to_lower_string((char*)r->profiles); ipike_to_lower_string((char*)r->mrru); ipike_to_lower_string((char*)r->integrity_alg); ipike_to_lower_string((char*)r->icv_len); *rohc = r; errout: if (err != IPIKE_SUCCESS) ipcom_free(r); return err; } /* *=========================================================================== * ipike_config_parse_ipsec_sa *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_ipsec_sa( Ipike_config *config, Ipike_config_api_ipsec_sa *sa, Ipike_config_api_proposal ***proposals, Ipike_config_api_rohc **rohc, char **ipsec_id) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* entry = IP_NULL; err = ipike_config_parse_flow(config, sa); if (err != IPIKE_SUCCESS) { IPCOM_LOG1(ERR, "Invalid flow for '%s'", config->name); return err; } while (err == IPIKE_SUCCESS && (entry = ipike_configuration_enum(config, entry))) { if (ipcom_strcasecmp(entry->name, "ipsec_id") == 0) { if (ipsec_id != IP_NULL) err = ipike_parse_string(entry->value, (const char**)ipsec_id); } else if (ipcom_strcasecmp(entry->name, "ike_id") == 0) { err = ipike_parse_string(entry->value, &sa->ike_id); } else if (ipcom_strcasecmp(entry->name, "encapsulation_mode") == 0) { err = ipike_parse_string(entry->value, &sa->encap_mode); } else if (ipcom_strcasecmp(entry->name, "use_tfc") == 0) { err = ipike_parse_string(entry->value, &sa->use_tfc); } else if (ipcom_strcasecmp(entry->name, "use_ecn") == 0) { err = ipike_parse_string(entry->value, &sa->use_ecn); } else if (ipcom_strcasecmp(entry->name, "dynamic_address") == 0) { err = ipike_parse_string(entry->value, &sa->dynamic_address); } else if (ipcom_strcasecmp(entry->name, "lifetime") == 0) { err = ipike_parse_string(entry->value, &sa->lifetime); } else if (ipcom_strcasecmp(entry->name, "proposal") == 0) { err = ipike_config_parse_proposal(entry, proposals); } else if (ipcom_strcasecmp(entry->name, "flowtype") == 0) { err = ipike_parse_string(entry->value, &sa->flowtype); } else if (ipcom_strcasecmp(entry->name, "granularity") == 0) { err = ipike_parse_string(entry->value, &sa->granularity); } else if (ipcom_strcasecmp(entry->name, "replay_window") == 0) { err = ipike_parse_number(entry->value, &sa->replay_window); } else if (ipcom_strcasecmp(entry->name, "rohc") == 0) { err = ipike_config_parse_rohc(entry, rohc); } else { IPCOM_LOG2(INFO, "Unknown '%s' entry for '%s', ignored...", entry->name, config->name); err = IPIKE_SUCCESS; } if (err == IPIKE_CONF_INVALID_VALUE) IPCOM_LOG3(ERR, "Invalid value '%s' for '%s' at '%s'", entry->value, entry->name, config->name); } return err; } /* *=========================================================================== * ipike_config_free_ipsec_sa *=========================================================================== */ IP_STATIC void ipike_config_free_ipsec_sa(Ipike_config_api_ipsec_sa* sa) { ipike_config_api_release_ipsec_sa(sa); } /* *=========================================================================== * ipike_config_parse_general *=========================================================================== */ IP_STATIC Ipike_error ipike_config_parse_general( Ipike_config* config, Ipike_config_api_general* general, Ipike_config_api_ike_sa* def_ike_sa, Ipike_config_api_proposal*** def_ike_proposals, Ipike_config_api_ipsec_sa* def_ipsec_sa, Ipike_config_api_proposal*** def_ipsec_proposals, Ipike_config_api_rohc** def_ipsec_rohc) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* entry = IP_NULL; /* Set all default that are non-zero */ general->spi_min = IPIKE_CONFIG_DEF_SPI_MIN; general->spi_max = IPIKE_CONFIG_DEF_SPI_MAX; general->retransmits = IPIKE_CONFIG_DEF_RETRANSMITS; def_ike_sa->passive = IP_TRUE; while ((IPIKE_SUCCESS == err) && (entry = ipike_configuration_enum(config, entry))) { if (ipcom_strcasecmp(entry->name, "listen") == 0) { err = ipike_parse_string(entry->value, &general->listen); } else if (ipcom_strcasecmp(entry->name, "retransmits") == 0) { err = ipike_parse_number(entry->value, &general->retransmits); } else if (ipcom_strcasecmp(entry->name, "exchange_max_time") == 0) { err = ipike_parse_number(entry->value, &general->exchange_max_time); } else if (ipcom_strcasecmp(entry->name, "spi_min") == 0) { err = ipike_parse_number(entry->value, &general->spi_min); } else if (ipcom_strcasecmp(entry->name, "spi_max") == 0) { err = ipike_parse_number(entry->value, &general->spi_max); } else if (ipcom_strcasecmp(entry->name, "default_ike_sa") == 0) { err = ipike_config_parse_ike_sa(entry, def_ike_sa, def_ike_proposals, IP_NULL); } else if (ipcom_strcasecmp(entry->name, "default_ipsec_sa") == 0) { err = ipike_config_parse_ipsec_sa(entry, def_ipsec_sa, def_ipsec_proposals, def_ipsec_rohc, IP_NULL); } else { IPCOM_LOG2(INFO, "Unknown '%s' entry for '%s', ignored...", entry->name, config->name); } if (IPIKE_SUCCESS != err) IPCOM_LOG3(ERR, "Invalid value '%s' for '%s' at '%s'", entry->value, entry->name, config->name); } return err; } /* *=========================================================================== * ipike_config_free_general *=========================================================================== */ IP_STATIC void ipike_config_free_general(Ipike_config_api_general* general) { ipike_config_api_release_general(general); return; } /* *=========================================================================== * ipike_config_file_set_ike_sa *=========================================================================== */ IP_STATIC Ipike_error ipike_config_file_set_ike_sa( void* config, const char* ike_id, Ipike_config_api_ike_sa* sa, Ipike_config_api_proposal** proposals) { Ipike_error err = IPIKE_SUCCESS; Ip_u32 i = 0; int id = IPIKE_CONFIG_INVALID_VALUE; err = ipike_config_api_set_ike_sa(config, ike_id, sa); if ( IPIKE_SUCCESS != err ) return err; if ( IP_NULL != proposals ) { for ( i = 0; proposals[i] != IP_NULL; i++) { id = (Ip_u8)(1 + i); err = ipike_config_api_set_ike_sa_proposal(config, ike_id, &id, proposals[i]); if (IPIKE_SUCCESS != err) break; } } return err; } /* *=========================================================================== * ipike_config_file_set_ipsec_sa *=========================================================================== */ IP_STATIC Ipike_error ipike_config_file_set_ipsec_sa( void* config, const char* ipsec_id, Ipike_config_api_ipsec_sa* sa, Ipike_config_api_proposal** proposals, Ipike_config_api_rohc* rohc) { Ipike_error err = IPIKE_SUCCESS; Ip_u32 i = 0; int id = IPIKE_CONFIG_INVALID_VALUE; err = ipike_config_api_set_ipsec_sa(config, ipsec_id, sa); if ( IPIKE_SUCCESS != err) return err; if ( IP_NULL != proposals ) { for ( i = 0; proposals[i] != IP_NULL; i++) { id = (Ip_u8)(1 + i); err = ipike_config_api_set_ipsec_sa_proposal(config, ipsec_id, &id, proposals[i]); if (IPIKE_SUCCESS != err) break; } } if ( IP_NULL != rohc ) ipike_config_api_set_ipsec_sa_rohc(config, ipsec_id, rohc); return err; } /* *=========================================================================== * ipike_config_generate_ipsec_id *=========================================================================== */ IP_STATIC char* ipike_config_generate_ipsec_id( Ipike_config_ipsec_sa** sas, const char* ike_id) { char* ipsec_id = IP_NULL; Ip_u32 count = 0; Ip_u32 i = 0; /* We require that a IKE id is specfied. We will generate the unique id * from ike_id and the number of times the ike is used. */ if (IP_NULL == ike_id) { IPCOM_LOG0(ERR, "No IKE SA id (ike_id) specified for IPSec SA"); } else { /* Append ipsec "counter" to ike_id */ count = 0; if (IP_NULL != sas) { while (IP_NULL != sas[i]) { if (IP_NULL != sas[i]->ike_id) if (!ipcom_strcmp(sas[i]->ike_id, ike_id)) count++; i++; } } ipsec_id = ipcom_malloc(ipcom_strlen(ike_id) + 8); if (IP_NULL != ipsec_id) ipcom_sprintf(ipsec_id, "%s_%d", ike_id, (int)count); } return ipsec_id; } /* *=========================================================================== * ipike_config_export_lifetime *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_lifetime( Ip_bool def, Ip_bool v1, const char* lifetime, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; if ((IP_NULL == lifetime) || (0 == lifetime[0])) return 0; /* Always require max length for buffer */ max_len = 32 + ipcom_strlen(lifetime); if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { buf_len = INVALID_LEN; } else { buf_len = 0; if (def) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " "); if (v1) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " v1_lifetime "); else buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " lifetime "); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s;\n", lifetime); } return buf_len; } /* *=========================================================================== * ipike_config_export_authentication *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_authentication( Ip_bool def, Ipike_config_api_ike_sa* ike_sa, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; char off[5] = {0}; /* Always require max length for buffer */ max_len = 32*10; if (IP_NULL != ike_sa->authentication.method) max_len += ipcom_strlen(ike_sa->authentication.method); if (IP_NULL != ike_sa->authentication.shared_key) max_len += ipcom_strlen(ike_sa->authentication.shared_key); if (IP_NULL != ike_sa->authentication.certificate) max_len += ipcom_strlen(ike_sa->authentication.certificate); if (IP_NULL != ike_sa->authentication.send_certificate) max_len += ipcom_strlen(ike_sa->authentication.send_certificate); if (IP_NULL != ike_sa->authentication.request_certificate) max_len += ipcom_strlen(ike_sa->authentication.request_certificate); if (IP_NULL != ike_sa->authentication.ocsp_response) max_len += ipcom_strlen(ike_sa->authentication.ocsp_response); if (IP_NULL != ike_sa->authentication.remote_certificate) max_len += ipcom_strlen(ike_sa->authentication.remote_certificate); if (IP_NULL != ike_sa->authentication.private_key) max_len += ipcom_strlen(ike_sa->authentication.private_key); if (IP_NULL != ike_sa->authentication.private_key_password) max_len += ipcom_strlen(ike_sa->authentication.private_key_password); if (IP_NULL != ike_sa->authentication.intermediate_ca_store) max_len += ipcom_strlen(ike_sa->authentication.intermediate_ca_store); if (IP_NULL != ike_sa->authentication.trusted_ca_store) max_len += ipcom_strlen(ike_sa->authentication.trusted_ca_store); if (IP_NULL != ike_sa->authentication.crl_store) max_len += ipcom_strlen(ike_sa->authentication.crl_store); if (IP_NULL != ike_sa->authentication.identity) max_len += ipcom_strlen(ike_sa->authentication.identity); if (IP_NULL != ike_sa->authentication.certificate_uri) max_len += ipcom_strlen(ike_sa->authentication.certificate_uri); if (max_len == 32*9) return 0; /* Nothing to export */ if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { buf_len = INVALID_LEN; } else { if (def) ipcom_strcpy(off, " "); buf_len = 0; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " authentication {\n"); if (IP_NULL != ike_sa->authentication.method) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " method %s;\n", ike_sa->authentication.method); } if (IP_NULL != ike_sa->authentication.shared_key) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " shared_key %s;\n", ike_sa->authentication.shared_key); } if (IP_NULL != ike_sa->authentication.certificate) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " certificate %s;\n", ike_sa->authentication.certificate); } if (IP_NULL != ike_sa->authentication.send_certificate) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " send_certificate %s;\n", ike_sa->authentication.send_certificate); } if (IP_NULL != ike_sa->authentication.request_certificate) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " request_certificate %s;\n", ike_sa->authentication.request_certificate); } if (IP_NULL != ike_sa->authentication.ocsp_response) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " ocsp_response %s;\n", ike_sa->authentication.ocsp_response); } if (IP_NULL != ike_sa->authentication.remote_certificate) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " remote_certificate %s;\n", ike_sa->authentication.remote_certificate); } if (IP_NULL != ike_sa->authentication.private_key) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " private_key %s;\n", ike_sa->authentication.private_key); } if (IP_NULL != ike_sa->authentication.private_key_password) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " private_key_password %s;\n", ike_sa->authentication.private_key_password); } if (IP_NULL != ike_sa->authentication.intermediate_ca_store) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " intermediate_ca_store %s;\n", ike_sa->authentication.intermediate_ca_store); } if (IP_NULL != ike_sa->authentication.trusted_ca_store) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " trusted_ca_store %s;\n", ike_sa->authentication.trusted_ca_store); } if (IP_NULL != ike_sa->authentication.crl_store) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " crl_store %s;\n", ike_sa->authentication.crl_store); } if (IP_NULL != ike_sa->authentication.identity) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " identity %s;\n", ike_sa->authentication.identity); } if (IP_NULL != ike_sa->authentication.certificate_uri) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " certificate_uri %s;\n", ike_sa->authentication.certificate_uri); } buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " }\n"); } return buf_len; } /* *=========================================================================== * ipike_config_export_radius *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_radius( Ip_bool def, Ipike_config_api_ike_sa* ike_sa, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; char off[5] = {0}; /* Always require max length for buffer */ max_len = 32*3; if (IP_NULL != ike_sa->radius.shared_secret) max_len += ipcom_strlen(ike_sa->radius.shared_secret); if (IP_NULL != ike_sa->radius.local_address) max_len += ipcom_strlen(ike_sa->radius.local_address); if (IP_NULL != ike_sa->radius.server_address) max_len += ipcom_strlen(ike_sa->radius.server_address); if (max_len == 32*3) return 0; /* Nothing to export */ if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { buf_len = INVALID_LEN; } else { if (def) ipcom_strcpy(off, " "); buf_len = 0; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " radius {\n"); if (IP_NULL != ike_sa->radius.shared_secret) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " shared_secret %s;\n", ike_sa->radius.shared_secret); } if (IP_NULL != ike_sa->radius.local_address) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " local_address %s;\n", ike_sa->radius.local_address); } if (IP_NULL != ike_sa->radius.server_address) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " server_address %s;\n", ike_sa->radius.server_address); } buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " }\n"); } return buf_len; } /* *=========================================================================== * ipike_config_export_proposal *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_proposal( Ip_bool def, Ipike_config_api_proposal* prop, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; Ip_size_t len = 0; char off[5] = {0}; /* Always require max length for buffer */ max_len = 6*32; if (IP_NULL != prop->dh_group) max_len += ipcom_strlen(prop->dh_group); if (IP_NULL != prop->encryption_alg) max_len += ipcom_strlen(prop->encryption_alg); if (IP_NULL != prop->hash_alg) max_len += ipcom_strlen(prop->hash_alg); if (IP_NULL != prop->integrity_alg) max_len += ipcom_strlen(prop->integrity_alg); if (IP_NULL != prop->use_esn) max_len += ipcom_strlen(prop->use_esn); if (IP_NULL != prop->number) max_len += ipcom_strlen(prop->number); max_len += ipike_config_export_lifetime(def, IP_TRUE, prop->v1.lifetime, IP_NULL, 0); if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { buf_len = INVALID_LEN; } else { if (def) ipcom_strcpy(off, " "); buf_len = 0; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " proposal {\n"); if (prop->number) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " number %s;\n", prop->number); } if (IP_NULL != prop->dh_group) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " dh_group %s;\n", prop->dh_group); } if (IP_NULL != prop->encryption_alg) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " encryption_algorithm %s;\n", prop->encryption_alg); } if (IP_NULL != prop->hash_alg) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " hash_algorithm %s;\n", prop->hash_alg); } if (IP_NULL != prop->integrity_alg) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " integrity_algorithm %s;\n", prop->integrity_alg); } if (IP_NULL != prop->use_esn) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " use_esn %s;\n", prop->use_esn); } len = ipike_config_export_lifetime(def, IP_TRUE, prop->v1.lifetime, &buf[buf_len], max_len - buf_len); if (INVALID_LEN == len) return INVALID_LEN; buf_len += len; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " }\n"); } return buf_len; } /* *=========================================================================== * ipike_config_export_flow *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_flow( Ipike_config_api_ipsec_sa* ipsec_sa, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; if ((IP_NULL == ipsec_sa->flow.src_address) || (IP_NULL == ipsec_sa->flow.dst_address)) return 0; /* Always require max length for buffer */ max_len = 32; max_len += ipcom_strlen(ipsec_sa->flow.src_address); max_len += ipcom_strlen(ipsec_sa->flow.dst_address); if (IP_NULL != ipsec_sa->flow.src_port) max_len += ipcom_strlen(ipsec_sa->flow.src_port); if (IP_NULL != ipsec_sa->flow.dst_port) max_len += ipcom_strlen(ipsec_sa->flow.dst_port); if (IP_NULL != ipsec_sa->flow.protocol) max_len += ipcom_strlen(ipsec_sa->flow.protocol); /* Address/port range support */ if (IP_NULL != ipsec_sa->flow_end.src_address) max_len += (ipcom_strlen(ipsec_sa->flow_end.src_address) + 1); if (IP_NULL != ipsec_sa->flow_end.dst_address) max_len += (ipcom_strlen(ipsec_sa->flow_end.dst_address) + 1); if (IP_NULL != ipsec_sa->flow_end.src_port) max_len += (ipcom_strlen(ipsec_sa->flow_end.src_port) + 1); if (IP_NULL != ipsec_sa->flow_end.dst_port) max_len += (ipcom_strlen(ipsec_sa->flow_end.dst_port) + 1); if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { buf_len = INVALID_LEN; } else { buf_len = 0; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "address %s", ipsec_sa->flow.src_address); if (IP_NULL != ipsec_sa->flow_end.src_address) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "-%s", ipsec_sa->flow_end.src_address); if (IP_NULL != ipsec_sa->flow.src_port) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " %s", ipsec_sa->flow.src_port); if (IP_NULL != ipsec_sa->flow_end.src_port) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "-%s", ipsec_sa->flow_end.src_port); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " address %s", ipsec_sa->flow.dst_address); if (IP_NULL != ipsec_sa->flow_end.dst_address) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "-%s", ipsec_sa->flow_end.dst_address); if (IP_NULL != ipsec_sa->flow.dst_port) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " %s", ipsec_sa->flow.dst_port); if (IP_NULL != ipsec_sa->flow_end.dst_port) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "-%s", ipsec_sa->flow_end.dst_port); if (IP_NULL != ipsec_sa->flow.protocol) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " %s", ipsec_sa->flow.protocol); } return buf_len; } /* *=========================================================================== * ipike_config_export_rohc *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_rohc( Ip_bool def, Ipike_config_api_rohc * rohc, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; char off[5] = {0}; /* Nothing to export */ if ( IP_NULL == rohc ) return 0; /* Always require max length for buffer */ max_len = 32*5; if (IP_NULL != rohc) { if (IP_NULL != rohc->max_cid ) max_len += ipcom_strlen(rohc->max_cid); if (IP_NULL != rohc->mrru ) max_len += ipcom_strlen(rohc->mrru); if (IP_NULL != rohc->profiles ) max_len += ipcom_strlen(rohc->profiles); if (IP_NULL != rohc->icv_len ) max_len += ipcom_strlen(rohc->icv_len); if (IP_NULL != rohc->integrity_alg ) max_len += ipcom_strlen(rohc->integrity_alg); } if (IP_NULL == buf) { buf_len = max_len; /* No buffer provided, just calculate the required buf_len and return */ return IPIKE_SUCCESS; } if ( buf_len < max_len ) return INVALID_LEN; if (def) ipcom_strcpy(off, " "); buf_len = 0; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " rohc {\n"); if (IP_NULL != rohc->mrru ) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " mrru %s;\n", rohc->mrru); } if (IP_NULL != rohc->profiles ) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " profiles %s;\n", rohc->profiles); } if (IP_NULL != rohc->max_cid ) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " max_cid %s;\n", rohc->max_cid); } if (IP_NULL != rohc->integrity_alg ) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " integrity_algorithm %s;\n", rohc->integrity_alg); } if (IP_NULL != rohc->icv_len ) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " icv_len %s;\n", rohc->icv_len); } buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " }\n"); return buf_len; } /* *=========================================================================== * ipike_config_export_ike_sa *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_ike_sa( const char* ike_id, Ipike_config_api_ike_sa* ike_sa, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; Ip_size_t len = 0; char off[5] = {0}; if ((IP_NULL == ike_sa) || (IP_NULL == ike_id)) return 0; /* Always require max length for buffer */ max_len = 256; max_len += ipcom_strlen(ike_id); max_len += ipike_config_export_authentication(IP_TRUE, ike_sa, IP_NULL, 0); max_len += ipike_config_export_radius(IP_TRUE, ike_sa, IP_NULL, 0); if (IP_NULL != ike_sa->version) max_len += ipcom_strlen(ike_sa->version); if (IP_NULL != ike_sa->local_address) max_len += ipcom_strlen(ike_sa->local_address); if (IP_NULL != ike_sa->remote_address) max_len += ipcom_strlen(ike_sa->remote_address); if (IP_NULL != ike_sa->local_id) max_len += ipcom_strlen(ike_sa->local_id); if (IP_NULL != ike_sa->remote_id) max_len += ipcom_strlen(ike_sa->remote_id); if (IP_NULL != ike_sa->lifetime) max_len += ipcom_strlen(ike_sa->lifetime); if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { return INVALID_LEN; } else { buf_len = 0; if (0 == ike_id[0]) { ipcom_strcpy(off, " "); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " default_ike_sa {\n"); } else { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "ike_sa address %s {\n", ike_sa->remote_address); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " ike_id %s;\n", ike_id); } if (IP_NULL != ike_sa->version) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " exchange_version %s;\n", ike_sa->version); } if (IP_NULL != ike_sa->mode) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " exchange_mode %s;\n", ike_sa->mode); } if (IP_NULL != ike_sa->local_address) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " local_address %s;\n", ike_sa->local_address); } buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " passive %s;\n", ike_sa->passive ? "on" : "off"); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " initial_contact %s;\n", ike_sa->initial_contact ? "on" : "off"); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " reauth %s;\n", ike_sa->reauth ? "yes" : "no"); if (ike_sa->liveness >= 0) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " liveness %lu;\n", ike_sa->liveness); } if (IP_NULL != ike_sa->local_id) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " local_identifier %s;\n", ike_sa->local_id); } if (IP_NULL != ike_sa->remote_id) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " remote_identifier %s;\n", ike_sa->remote_id); } len = ipike_config_export_lifetime((0 == ike_id[0]), IP_FALSE, ike_sa->lifetime, &buf[buf_len], max_len - buf_len); if (INVALID_LEN == len) return INVALID_LEN; buf_len += len; len = ipike_config_export_authentication((0 == ike_id[0]), ike_sa, &buf[buf_len], max_len - buf_len); if (INVALID_LEN == len) return INVALID_LEN; buf_len += len; len = ipike_config_export_radius((0 == ike_id[0]), ike_sa, &buf[buf_len], max_len - buf_len); if (INVALID_LEN == len) return INVALID_LEN; buf_len += len; } return buf_len; } /* *=========================================================================== * ipike_config_export_ipsec_sa *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_ipsec_sa( const char* ipsec_id, Ipike_config_api_ipsec_sa* ipsec_sa, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; Ip_size_t len = 0; char off[5] = {0}; if ((IP_NULL == ipsec_sa) || (IP_NULL == ipsec_id)) return 0; /* Always require max length for buffer */ max_len = 128; max_len += ipike_config_export_lifetime((ipsec_id[0] == IP_NULL), IP_FALSE, ipsec_sa->lifetime, IP_NULL, 0); max_len += ipike_config_export_flow(ipsec_sa, IP_NULL, 0); if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { return INVALID_LEN; } else { buf_len = 0; if (ipsec_id[0] == 0) { ipcom_strcpy(off, " "); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " default_ipsec_sa {\n"); } else { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "ipsec_sa "); len = ipike_config_export_flow(ipsec_sa, &buf[buf_len], max_len - buf_len); if (INVALID_LEN == len) return INVALID_LEN; buf_len += len; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " {\n"); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " ipsec_id %s;\n", ipsec_id); } if (IP_NULL != ipsec_sa->ike_id) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " ike_id %s;\n", ipsec_sa->ike_id); } if (IP_NULL != ipsec_sa->encap_mode) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " encapsulation_mode %s;\n", ipsec_sa->encap_mode); } if (IP_NULL != ipsec_sa->use_tfc) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " use_tfc %s;\n", ipsec_sa->use_tfc); } if (IP_NULL != ipsec_sa->use_ecn) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " use_ecn %s;\n", ipsec_sa->use_ecn); } if (IP_NULL != ipsec_sa->dynamic_address) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " dynamic_address %s;\n", ipsec_sa->dynamic_address); } if (IP_NULL != ipsec_sa->flowtype) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " flowtype %s;\n", ipsec_sa->flowtype); } if (IP_NULL != ipsec_sa->granularity) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " granularity %s;\n", ipsec_sa->granularity); } if (0 != ipsec_sa->replay_window) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s", off); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " replay_window %d;\n", ipsec_sa->replay_window); } len = ipike_config_export_lifetime((ipsec_id[0] == 0), IP_FALSE, ipsec_sa->lifetime, &buf[buf_len], max_len - buf_len); if (INVALID_LEN == len) return INVALID_LEN; buf_len += len; } return buf_len; } /* *=========================================================================== * ipike_config_export_general *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_general( Ipike_config_api_general* general, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; /* Always require max length for buffer */ max_len = 128; if (IP_NULL != general->listen) max_len += ipcom_strlen(general->listen); if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { buf_len = INVALID_LEN; } else { buf_len = 0; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "general {\n"); if (IP_NULL != general->listen) buf_len += (Ip_size_t) ipcom_sprintf(&buf[buf_len], " listen %s;\n", general->listen); if (general->retransmits != IPIKE_CONFIG_DEF_RETRANSMITS) buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " retransmits %lu;\n", general->retransmits); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " exchange_max_time %lu;\n", general->exchange_max_time); if ((general->spi_min != IPIKE_CONFIG_DEF_SPI_MIN) || (general->spi_max != IPIKE_CONFIG_DEF_SPI_MAX)) { buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " spi_min %lu;\n", general->spi_min); buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], " spi_max %lu;\n", general->spi_max); } } return buf_len; } /* *=========================================================================== * ipike_config_export_section_end *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_section_end( const char* off, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; /* Always require max length for buffer */ max_len = 2; max_len += ipcom_strlen(off); if (IP_NULL == buf) { buf_len = max_len; } else if (buf_len < max_len) { buf_len = INVALID_LEN; } else { buf_len = 0; buf_len += (Ip_size_t)ipcom_sprintf(&buf[buf_len], "%s}\n", off); } return buf_len; } /* *=========================================================================== * ipike_config_export_ike_sa_with_proposals *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_ike_sa_with_proposals( void* ctx, const char* ike_id, Ipike_config_api_ike_sa* ike_sa, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; Ip_size_t len = 0; int id_prop = 0; int pos_prop = 0; Ipike_config_api_proposal proposal = {0}; max_len = buf_len; buf_len = 0; len = ipike_config_export_ike_sa(ike_id, ike_sa, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; pos_prop = IPIKE_CONFIG_INVALID_VALUE; while (IPIKE_SUCCESS == ipike_config_api_get_next_ike_sa_proposal(ctx, ike_id, &id_prop, &proposal, &pos_prop)) { len = ipike_config_export_proposal((ike_id[0] == 0), &proposal, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; ipike_config_api_release_proposal(&proposal); } len = ipike_config_export_section_end((ike_id[0] == 0) ? " " : "", buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; return buf_len; } /* *=========================================================================== * ipike_config_export_ipsec_sa_with_proposals *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_ipsec_sa_with_proposals( void* ctx, const char* ipsec_id, Ipike_config_api_ipsec_sa* ipsec_sa, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; Ip_size_t len = 0; int id_prop = 0; int pos_prop = 0; Ipike_config_api_proposal proposal = {0}; Ipike_config_api_rohc rohc = {0}; max_len = buf_len; buf_len = 0; len = ipike_config_export_ipsec_sa(ipsec_id, ipsec_sa, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; if ( IPIKE_SUCCESS == ipike_config_api_get_ipsec_sa_rohc(ctx, ipsec_id, &rohc) ) { len = ipike_config_export_rohc(ipsec_id[0] == 0, &rohc, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; } pos_prop = IPIKE_CONFIG_INVALID_VALUE; while (IPIKE_SUCCESS == ipike_config_api_get_next_ipsec_sa_proposal(ctx, ipsec_id, &id_prop, &proposal, &pos_prop)) { len = ipike_config_export_proposal((ipsec_id[0] == 0), &proposal, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; ipike_config_api_release_proposal(&proposal); } len = ipike_config_export_section_end((ipsec_id[0] == 0) ? " " : "", buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; return buf_len; } /* *=========================================================================== * ipike_config_export_general_with_default *=========================================================================== */ IP_STATIC Ip_size_t ipike_config_export_general_with_default( void* ctx, Ipike_config_api_general* general, char* buf, Ip_size_t buf_len) { Ip_size_t max_len = 0; Ip_size_t len = 0; int pos = 0; char id[IPIKE_CONFIG_MAX_ID_LEN] = {0}; Ipike_config_api_ike_sa ike_sa = {0}; Ipike_config_api_ipsec_sa ipsec_sa = {0}; max_len = buf_len; buf_len = 0; len = ipike_config_export_general(general, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; pos = IPIKE_CONFIG_INVALID_VALUE; while (IPIKE_SUCCESS == ipike_config_api_get_next_ike_sa(ctx, id, &ike_sa, &pos)) { if (id[0] == 0) { len = ipike_config_export_ike_sa_with_proposals(ctx, id, &ike_sa, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; ipike_config_api_release_ike_sa(&ike_sa); /* Only one default entry */ break; } ipike_config_api_release_ike_sa(&ike_sa); } pos = IPIKE_CONFIG_INVALID_VALUE; while (IPIKE_SUCCESS == ipike_config_api_get_next_ipsec_sa(ctx, id, &ipsec_sa, &pos)) { if (id[0] == 0) { len = ipike_config_export_ipsec_sa_with_proposals(ctx, id, &ipsec_sa, buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; ipike_config_api_release_ipsec_sa(&ipsec_sa); /* Only one default entry */ break; } ipike_config_api_release_ipsec_sa(&ipsec_sa); } len = ipike_config_export_section_end("", buf, max_len - buf_len); if (len == INVALID_LEN) return INVALID_LEN; buf_len += len; if (IP_NULL != buf) buf += len; return buf_len; } /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipike_config_file_import_content *=========================================================================== */ IP_GLOBAL Ipike_error ipike_config_file_import_content( Ipike_config_ike* config, const char* buf, Ip_size_t buf_len) { Ipike_error err = IPIKE_SUCCESS; Ipike_config* content = IP_NULL; Ipike_config* entry = IP_NULL; Ipike_config_api_general general; Ipike_config_api_ike_sa ike_sa; Ipike_config_api_ipsec_sa ipsec_sa; Ipike_config_api_proposal** ike_proposal = IP_NULL; Ipike_config_api_proposal** ipsec_proposal = IP_NULL; Ipike_config_api_rohc* ipsec_rohc = IP_NULL; char* ike_id = IP_NULL; char* ipsec_id = IP_NULL; ipcom_memset(&general, 0, sizeof(Ipike_config_api_general)); ipcom_memset(&ike_sa, 0, sizeof(Ipike_config_api_ike_sa)); ipcom_memset(&ipsec_sa, 0, sizeof(Ipike_config_api_ipsec_sa)); err = ipike_configuration_new(buf, buf_len, &content); if (IPIKE_SUCCESS != err) { IPCOM_LOG0(ERR, "Failed to parse the configuration"); goto errout; } while ( (entry = ipike_configuration_enum(content, entry)) != IP_NULL ) { if (ipcom_strcasecmp(entry->name, "general") == 0) { err = ipike_config_parse_general(entry, &general, &ike_sa, &ike_proposal, &ipsec_sa, &ipsec_proposal, &ipsec_rohc); if (IPIKE_SUCCESS == err) err = ipike_config_api_set_general(config, &general); if (IPIKE_SUCCESS == err) err = ipike_config_file_set_ike_sa(config, IP_NULL, &ike_sa, ike_proposal); if (IPIKE_SUCCESS == err) err = ipike_config_file_set_ipsec_sa(config, IP_NULL, &ipsec_sa, ipsec_proposal, ipsec_rohc); ipike_config_free_general(&general); ipike_config_free_ike_sa(&ike_sa); ipike_config_free_ipsec_sa(&ipsec_sa); ipike_config_free_proposals(&ike_proposal); ipike_config_free_proposals(&ipsec_proposal); ipike_config_free_rohc(&ipsec_rohc); } else if (ipcom_strcasecmp(entry->name, "ike_sa") == 0) { /* Set non string parameters as unspecified */ ike_sa.liveness = -1; /* Unassigned value now is -1 */ ike_sa.reauth = IPIKE_CONFIG_UNSPEC_BOOL; ike_sa.passive = IPIKE_CONFIG_UNSPEC_BOOL; ike_sa.initial_contact = IPIKE_CONFIG_UNSPEC_BOOL; err = ipike_config_parse_ike_sa(entry, &ike_sa, &ike_proposal, &ike_id); if (IPIKE_SUCCESS == err) err = ipike_config_file_set_ike_sa(config, ike_id, &ike_sa, ike_proposal); IPIKE_FREEP(ike_id); ipike_config_free_ike_sa(&ike_sa); ipike_config_free_proposals(&ike_proposal); } else if (ipcom_strcasecmp(entry->name, "ipsec_sa") == 0) { err = ipike_config_parse_ipsec_sa(entry, &ipsec_sa, &ipsec_proposal, &ipsec_rohc, &ipsec_id); if (IP_NULL == ipsec_id) ipsec_id = ipike_config_generate_ipsec_id(config->ipsec_sa, ipsec_sa.ike_id); if (IPIKE_SUCCESS == err) err = ipike_config_file_set_ipsec_sa(config, ipsec_id, &ipsec_sa, ipsec_proposal, ipsec_rohc); IPIKE_FREEP(ipsec_id); ipike_config_free_ipsec_sa(&ipsec_sa); ipike_config_free_proposals(&ipsec_proposal); ipike_config_free_rohc(&ipsec_rohc); } else if (ipcom_strcasecmp(entry->name, "append_existing") == 0) { /* For shell command: "ike config load ". */ } else { IPCOM_LOG1(INFO, "Unknown configuration entry '%s', ignored...", entry->name); } } errout: ipike_configuration_free(content); return err; } /* *=========================================================================== * ipike_config_file_export_content *=========================================================================== */ IP_GLOBAL Ipike_error ipike_config_file_export_content( Ipike_config_ike* config, char* buf, Ip_size_t* buf_len) { Ipike_error err = IPIKE_SUCCESS; Ip_size_t max_len = 0; Ip_size_t len = 0; char id[IPIKE_CONFIG_MAX_ID_LEN] = {0}; int pos = 0; void* ctx = IP_NULL; Ipike_config_api_general general = {0}; Ipike_config_api_ike_sa ike_sa = {0}; Ipike_config_api_ipsec_sa ipsec_sa = {0}; max_len = *buf_len; *buf_len = 0; ctx = ipike_config_api_from_config(config); if (IP_NULL == ctx) { IP_PANIC(); return IPIKE_OUT_OF_MEMORY; } if (IPIKE_SUCCESS == ipike_config_api_get_general(ctx, &general)) { len = ipike_config_export_general_with_default(ctx, &general, buf, max_len - *buf_len); if (len == INVALID_LEN) { err = IPIKE_BUFFER_TOO_SMALL; } else { *buf_len += len; if (IP_NULL != buf) buf += len; } ipike_config_api_release_general(&general); } pos = IPIKE_CONFIG_INVALID_VALUE; while ((IPIKE_SUCCESS == err) && (IPIKE_SUCCESS == ipike_config_api_get_next_ike_sa(ctx, id, &ike_sa, &pos))) { if (id[0] != 0) { len = ipike_config_export_ike_sa_with_proposals(ctx, id, &ike_sa, buf, max_len - *buf_len); if (len == INVALID_LEN) { err = IPIKE_BUFFER_TOO_SMALL; } else { *buf_len += len; if (IP_NULL != buf) buf += len; } } ipike_config_api_release_ike_sa(&ike_sa); } pos = IPIKE_CONFIG_INVALID_VALUE; while ((IPIKE_SUCCESS == err) && (IPIKE_SUCCESS == ipike_config_api_get_next_ipsec_sa(ctx, id, &ipsec_sa, &pos))) { if (id[0] != 0) { len = ipike_config_export_ipsec_sa_with_proposals(ctx, id, &ipsec_sa, buf, max_len - *buf_len); if (len == INVALID_LEN) { err = IPIKE_BUFFER_TOO_SMALL; } else { *buf_len += len; if (IP_NULL != buf) buf += len; } } ipike_config_api_release_ipsec_sa(&ipsec_sa); } ipike_config_api_free(ctx); return err; } /* **************************************************************************** * END OF FILE **************************************************************************** */