/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_exchange_aggressive_mode.c,v $ $Revision: 1.21.10.11 $ * $Source: /home/interpeak/CVSRoot/ipike/src/ipike_exchange_aggressive_mode.c,v $ * $Author: zan $ $Date: 2013-08-01 02:00:39 $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipike_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #ifdef IPIKE_USE_AGGRESSIVE_MODE #include "ipike_h.h" #include "ipike_exchange_aggressive_mode.h" #include "ipike_exchange_main_mode.h" #include "ipike_exchange_informational.h" #include "ipike_crypto.h" #include "ipike_payload.h" #include "ipike_attributes.h" #include "ipike_payload_sa.h" #include "ipike_payload_certificate.h" #include "ipike_payload_key_exchange.h" #include "ipike_payload_nonce.h" #include "ipike_payload_identification.h" #include "ipike_payload_notification.h" #include "ipike_payload_hash.h" #include "ipike_payload_sign.h" #include "ipike_payload_transform.h" #include "ipike_payload_vendor_id.h" #include "ipike_payload_nat.h" #include "ipike_util.h" #include "ipike_sadb.h" #include "ipike_ipsec.h" #include "ipike_configuration.h" #include "ipike_policy.h" #include #include #include #include #include /* **************************************************************************** * 4 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 5 DEFINES **************************************************************************** */ /* **************************************************************************** * 6 TYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipike_aggressive_mode_authentication_add *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_authentication_add(Ipike_isakmp_exchange* ie) { Ipike_error err; Ip_u16 auth_meth; Ip_u16 hash_alg; Ipike_value* hash; Ipike_value* sign; Ipike_transform_ike *transform_ike; transform_ike=ipike_transform_ike_from_exch(ie); if (transform_ike==IP_NULL) return IPIKE_FAILED; auth_meth = transform_ike->authentication_method; if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES) hash_alg = IPIKE_ATTR_HASH_SHA1; else hash_alg = ipike_transform_ike_from_exch(ie)->hash_algorithm; if (ie->ike_sa->is_initiator) { hash = &ie->ike_sa->hash_i; sign = &ie->ike_sa->sign_i; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_hash_i(hash_alg, ie->ike_sa, hash))) return err; } else { hash = &ie->ike_sa->hash_r; sign = &ie->ike_sa->sign_r; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_hash_r(hash_alg, ie->ike_sa, hash))) return err; } if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES) err = ipike_crypto_compute_dsa_sign(ie->ike_conf->authentication.key_id, ie->ike_conf->authentication.private_key, hash, sign); else if (auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES) err = ipike_crypto_compute_rsa_sign(ie->ike_conf->authentication.key_id, ie->ike_conf->authentication.private_key, hash, sign); if (IPIKE_SUCCESS == err) return err; return err; } /* *=========================================================================== * ipike_aggressive_mode_authentication_check *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_authentication_check(Ipike_isakmp_exchange* ie) { return ipike_main_mode_authentication_check(ie); } /* *=========================================================================== * ipike_aggressive_mode_cert_update_responder_config *=========================================================================== */ IP_STATIC void ipike_aggressive_mode_update_responder_config(Ipike_isakmp_exchange *ie) { ipike_main_mode_update_responder_config(ie); } /* This IKE daemon is responder */ /* *=========================================================================== * ipike_aggressive_mode_update_after_msg_1 *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_update_after_msg_1(Ipike_isakmp_exchange* ie) { Ipike_error err; Ipike_transform_ike* transform; /* Check if there is a more suitable IKE SA config */ ipike_aggressive_mode_update_responder_config(ie); err = ipike_policy_select_ike_sa_param(ie->ike_conf, &ie->ike_sa->sa, &ie->ike_sa->selected, IP_FALSE); if (IPIKE_SUCCESS != err) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\ "select SA failed"); IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, PROPOSAL_MISMATCH, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); /* Log and return */ return err; } if (IPIKE_SUCCESS != (err = ipike_payload_nonce_generate(&ie->ike_sa->nr))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\ "nonce generation failed"); goto errout; } transform = ipike_transform_ike_from_exch(ie); if (transform==IP_NULL) { err=IPIKE_FAILED; goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_generate_dh_key( transform->dh_prime, transform->dh_generator, &ie->dh, &ie->ike_sa->g_xr))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() ::"\ " DH key generation failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key( ie->dh, &ie->ike_sa->g_xi, &ie->ike_sa->g_xy))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\ "compute DH key failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid( ie->ike_conf, ie->ike_sa))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\ " compute skeyid failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\ " compute phase1 failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv( ie->ike_sa, &ie->iv))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_1() :: "\ "compute initial iv failed"); goto errout; } if ((IP_NULL == ie->ike_conf->local_id) || (IPIKE_SUCCESS != ipike_identification_generate(ie->ike_conf->local_id, &ie->ike_sa->idir))) { if (IPIKE_SUCCESS != (err = ipike_ipsec_set_idix(&ie->ike_sa->local_addr, &ie->ike_sa->idir))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\ "id initialize failed"); goto errout; } } if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_add(ie))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\ "add authentication failed"); goto errout; } return IPIKE_SUCCESS; errout: /* Log general IKE error */ IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } /* *=========================================================================== * ipike_aggressive_mode_update_after_msg_3 *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_update_after_msg_3(Ipike_isakmp_exchange* ie) { Ipike_error err; if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_check(ie))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_3() :: "\ "authentication check failed"); IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, AUTHENTICATION_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } /* Everything should be encrypted from now on */ ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION; return IPIKE_SUCCESS; } /* This IKE daemon is initiator */ /* *=========================================================================== * ipike_aggressive_mode_update_before_msg_1 *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_update_before_msg_1(Ipike_isakmp_exchange* ie) { Ipike_error err; Ipike_transform_ike* transform; /* Try to use id from configuration, use ip-address if fails */ if ((IP_NULL == ie->ike_conf->local_id) || (IPIKE_SUCCESS != ipike_identification_generate(ie->ike_conf->local_id, &ie->ike_sa->idii))) { if (IPIKE_SUCCESS != (err = ipike_ipsec_set_idix(&ie->ike_sa->local_addr, &ie->ike_sa->idii))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() ::"\ "id initialize failed"); goto errout; } } /* Initialize SA */ if (IPIKE_SUCCESS != (err = ipike_sa_ike_initialize(ie->ike_conf, &ie->ike_sa->sa))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\ "SA initialize failed"); goto errout; } /* Initialize KE */ transform = &ie->ike_sa->sa.proposals[0]->transforms[0]->ike; if (IPIKE_SUCCESS != (err = ipike_crypto_generate_dh_key( transform->dh_prime, transform->dh_generator, &ie->dh, &ie->ike_sa->g_xi))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\ "DH key generation failed"); goto errout; } /* Initialize NONCE */ if (IPIKE_SUCCESS != (err = ipike_payload_nonce_generate(&ie->ike_sa->ni))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\ "nonce generation failed"); goto errout; } return IPIKE_SUCCESS; errout: /* Log general IKE error */ IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } /* *=========================================================================== * ipike_aggressive_mode_update_after_msg_2 *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_update_after_msg_2(Ipike_isakmp_exchange* ie) { Ipike_sadb_entry* ike_sa = ie->ike_sa; Ipike_error err; err = ipike_policy_select_ike_sa_param(ie->ike_conf, &ike_sa->sa, &ike_sa->selected, IP_TRUE); if (IPIKE_SUCCESS != err) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\ "select SA failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key( ie->dh, &ike_sa->g_xr, &ike_sa->g_xy))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\ "compute DH key failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid( ie->ike_conf, ike_sa))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\ "compute skeyid failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\ "compute phase1 failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv( ike_sa, &ie->iv))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\ "compute initial iv failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_check(ie))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_after_msg_2() :: "\ "authentication check failed"); goto errout; } if (IPIKE_SUCCESS != (err = ipike_aggressive_mode_authentication_add(ie))) { IPCOM_LOG0(DEBUG, "ipike_aggressive_mode_update_before_msg_1() :: "\ "add authentication failed"); goto errout; } /* Everything should be encrypted from now on */ ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION; return IPIKE_SUCCESS; errout: /* Log general IKE error */ IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } /* *=========================================================================== * ipike_aggressive_mode_update_state *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_update_state(Ipike_isakmp_exchange* ie) { switch (ie->message_number) { /* We are responder */ case 1: return ipike_aggressive_mode_update_after_msg_1(ie); case 3: return ipike_aggressive_mode_update_after_msg_3(ie); /* We are initiator */ case 0: return ipike_aggressive_mode_update_before_msg_1(ie); case 2: return ipike_aggressive_mode_update_after_msg_2(ie); } IPCOM_LOG1(ERR, "IKE aggressive mode has 3 messages, this was %d", ie->message_number); IPIKE_EVENT_LOG(IKE_PACKET_DISCARD, ISAKMP_PACKET_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return IPIKE_INVALID_MESSAGE_NUMBER; } /* *=========================================================================== * ipike_aggressive_mode_store_sai_b *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_store_sai_b(Ipike_value* sai_b, Ipike_sa_payload* payload) { sai_b->len = ip_ntohs(payload->header.length) - IPIKE_PAYLOAD_HEADER_LENGTH; if (IP_NULL == (sai_b->value = ipcom_malloc(sai_b->len))) { IP_PANIC(); return IPIKE_OUT_OF_MEMORY; } ipcom_memcpy(sai_b->value, (Ip_u8 *) payload + IPIKE_PAYLOAD_HEADER_LENGTH, sai_b->len); return IPIKE_SUCCESS; } /* *=========================================================================== * ipike_aggressive_mode_cert_create *=========================================================================== */ IP_STATIC Ipike_error ipike_aggressive_mode_cert_create( Ipike_config_ike_sa* conf, Ipike_cert_payload** payload) { Ipike_error err; Ipike_cert cert; cert.peer = ipike_crypto_read_cert(conf->authentication.certificate); err = ipike_payload_certificate_create(cert.peer, IP_NULL, payload); X509_free(cert.peer); return err; } /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipike_aggressive_mode_on_new_exchange_initiator *=========================================================================== */ IP_PUBLIC Ipike_error ipike_aggressive_mode_on_new_exchange_initiator( Ipike_isakmp_exchange* ie, Ipike_sadb_entry* ike_sa, const void* option1, const void* trigger_flow) { Ipike_error err; Ip_u8 initiator_cookie[IPIKE_ISAKMP_COOKIE_SIZE]; Ip_u8 responder_cookie[IPIKE_ISAKMP_COOKIE_SIZE]; union Ip_sockaddr_union peer_addr; union Ip_sockaddr_union local_addr; Ipike_config_flow *flow = IP_NULL; /* IKE v1 */ ie->version = 1 << 4; /* Store option1, only establish IKE SA if set */ ie->option1 = option1; if (trigger_flow != IP_NULL) { /* Make a copy of the flow information, we will need to pass this * further to the IPsec SA establishment */ flow = ipike_config_flow_duplicate(trigger_flow); if ( flow == IP_NULL ) { IP_PANIC(); return IPIKE_OUT_OF_MEMORY; } /* Store the flow in the place holder for option2*/ ie->option2 = flow; } ipcom_microtime(&ie->start); ipcom_memset(responder_cookie, 0, IPIKE_ISAKMP_COOKIE_SIZE); err = ipike_crypto_generate_cookie(initiator_cookie); if (IPIKE_SUCCESS != err) return err; /* Do we have an IKE SA, i.e. this is a reauthentication */ if (ike_sa != IP_NULL) { /* Use the same addresses and ports as the old IKE SA */ err = ipike_addr_copy(&local_addr, &ike_sa->local_addr); if (IPIKE_SUCCESS != err) return err; err = ipike_addr_copy(&peer_addr, &ike_sa->peer_addr); if (IPIKE_SUCCESS != err) return err; } else { /* Use local address from configuration */ err = ipike_addr_copy(&local_addr, &ie->ike_conf->local_address); if (IPIKE_SUCCESS != err) return err; /* Check if we have a valid host address in the configuration */ if ( ipike_config_netobj_is_host(&ie->ike_conf->remote_address) ) { /* Use remote address from configuration */ err = ipike_addr_copy(&peer_addr, &ie->ike_conf->remote_address.addr); if (IPIKE_SUCCESS != err) return err; } /* Was this negotiation triggered by a flow */ else if (flow != IP_NULL) { /* Use remote address from the trigger flow */ err = ipike_addr_copy(&peer_addr, &flow->dst[0]->addr); if (IPIKE_SUCCESS != err) return err; } else { /* No idea of the remote address */ return IPIKE_CONF_INVALID_VALUE; } /* Reset destination port to default IKE port (500) */ ipike_addr_set_port(&peer_addr, ipike.port); } if (ipike_addr_is_any(&local_addr)) { /* Try to figure out our local address based on the peer address */ err = ipike_dispatcher_socket_local_addr_get(&local_addr, &peer_addr); if (err != IPIKE_SUCCESS) { IPCOM_LOG0(NOTICE, "ipike_aggressive_mode_on_new_exchange_initiator() ::"\ " failed to get local address"); /* Ignore error, the stack will find out the address * eventually, however NAT-T will fail because of * mismatching hashes */ } } err = ipike_sadb_add(initiator_cookie, responder_cookie, &local_addr, &peer_addr, &ie->ike_sa); if (err != IPIKE_SUCCESS) return err; ie->is_phase1 = IP_TRUE; ie->exchange_initiator = IP_TRUE; ie->ike_sa->is_initiator = IP_TRUE; ie->ike_sa->id = ipcom_strdup(ie->ike_conf->ike_id); ie->ike_sa->version = ie->version; ie->ike_sa->has_got_natt_capability = IP_FALSE; return ipike_aggressive_mode_update_state(ie); } /* *=========================================================================== * ipike_aggressive_mode_on_new_exchange_responder *=========================================================================== */ IP_PUBLIC Ipike_error ipike_aggressive_mode_on_new_exchange_responder( Ipike_isakmp_exchange* ie, Ipike_isakmp_header* first_isakmp, union Ip_sockaddr_union* local_addr, union Ip_sockaddr_union* peer_addr) { Ipike_error err; Ip_u8 responder_cookie[IPIKE_ISAKMP_COOKIE_SIZE]; Ip_u8 retry; ipcom_microtime(&ie->start); /* IKE version 1 */ ie->version = 1 << 4; if (first_isakmp->message_id != 0) { IPCOM_LOG0(ERR, "ipike_aggressive_mode_on_new_exchange_responder: message id must be zero in this exchange"); err = IPIKE_ISAKMP_INVALID_MESSAGE_ID; } else { retry = 0; do { if (retry++ > 100) { IPCOM_LOG0(ERR, "ipike_aggressive_mode_on_new_exchange_responder: too many retries"); return IPIKE_FAILED; } /* Generate responder cookie until the initiator/responder * cookie pair is unique */ if (IPIKE_SUCCESS != (err = ipike_crypto_generate_cookie(responder_cookie))) return err; } while (ipike_sadb_exist(first_isakmp->initiator_cookie, responder_cookie)); if (IPIKE_SUCCESS != (err = ipike_sadb_add(first_isakmp->initiator_cookie, responder_cookie, local_addr, peer_addr, &ie->ike_sa))) { IPCOM_LOG0(ERR, "ipike_aggressive_mode_on_new_exchange_responder: failed to add sa"); } else { ie->is_phase1 = IP_TRUE; ie->ike_sa->is_initiator = IP_FALSE; ie->ike_sa->id = ipcom_strdup(ie->ike_conf->ike_id); ie->ike_sa->version = ie->version; ie->ike_sa->has_got_natt_capability=IP_FALSE; } } return err; } /* *=========================================================================== * ipike_aggressive_mode_on_delete_exchange *=========================================================================== */ IP_PUBLIC void ipike_aggressive_mode_on_delete_exchange(Ipike_isakmp_exchange* ie) { if (ie->ike_sa == IP_NULL) return; if (ie->message_number < ipike_isakmp_exchange_message_count(ie)) { IPCOM_LOG0(WARNING, "ipike_aggressive_mode_on_delete_exchange: the exchange was not finished," " removing (incomplete) IKE SA"); (void)ipike_sadb_set_state(ie, ie->ike_sa, IPIKE_SA_DYING); } if (ie->option2) ipike_config_flow_destroy((Ipike_config_flow *)ie->option2); } /* *=========================================================================== * ipike_aggressive_mode_get_payload_order *=========================================================================== */ IP_PUBLIC const Ip_u16 * ipike_aggressive_mode_get_payload_order(Ipike_isakmp_exchange* ie) { static Ip_u16 aggressive_mode_exchange[] = { /* message # 1 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_CERTIFICATE_REQUEST | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_VENDOR_ID | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD, IPIKE_PAYLOAD_NONE, /* message # 2 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_HASH | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_CERTIFICATE_REQUEST | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_SIGNATURE | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_VENDOR_ID | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD, IPIKE_PAYLOAD_NAT_DISCOVERY | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_NONE, /* message # 3 */ IPIKE_PAYLOAD_HASH | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_CERTIFICATE_REQUEST | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_SIGNATURE | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_NAT_DISCOVERY | IPIKE_PAYLOAD_OPT, IPIKE_PAYLOAD_NONE, }; int i = 1; Ip_u16 n = 0; Ip_u16* ret = aggressive_mode_exchange; Ip_u16 auth_method = 0; while (i != ie->message_number) if (*ret++ == IPIKE_PAYLOAD_NONE) i++; /* Some optional must be added depending on authentication mechanism */ ipike_attribute_auth_method_from_string(ie->ike_conf->authentication.method, &auth_method); i = 0; while (ret[i] != IPIKE_PAYLOAD_NONE) { n = (Ip_u16)(ret[i] & 0x3FFF); if ( auth_method == IPIKE_ATTR_AUTH_PRE_SHARED_KEY ) { switch (n) { case IPIKE_PAYLOAD_HASH: ret[i] |= IPIKE_PAYLOAD_ADD; break; case IPIKE_PAYLOAD_CERTIFICATE: case IPIKE_PAYLOAD_CERTIFICATE_REQUEST: case IPIKE_PAYLOAD_SIGNATURE: ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD); break; default: break; } } else { switch (n) { case IPIKE_PAYLOAD_HASH: ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD); break; case IPIKE_PAYLOAD_CERTIFICATE: if ( ipike_isakmp_should_send_certificate(ie) ) ret[i] |= IPIKE_PAYLOAD_ADD; else ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD); break; case IPIKE_PAYLOAD_CERTIFICATE_REQUEST: if ( ipike_isakmp_should_send_certificate_req(ie) ) ret[i] |= IPIKE_PAYLOAD_ADD; else ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD); break; case IPIKE_PAYLOAD_SIGNATURE: ret[i] |= IPIKE_PAYLOAD_ADD; break; default: break; } } i++; } /* Some optional must be added depending on NAT Traversal */ i = 0; while (ret[i] != IPIKE_PAYLOAD_NONE) { n = (Ip_u16)(ret[i] & 0x3FFF); if (n == IPIKE_PAYLOAD_NAT_DISCOVERY) { if (ipike.port_nat != 0 && ie->ike_sa->has_got_natt_capability) ret[i] |= IPIKE_PAYLOAD_ADD; else ret[i] = (Ip_u16)(ret[i] & ~IPIKE_PAYLOAD_ADD); } i++; } return ret; } /* *=========================================================================== * ipike_aggressive_mode_process_payloads *=========================================================================== */ IP_PUBLIC Ipike_error ipike_aggressive_mode_process_payloads( Ipike_isakmp_exchange *ie, Ipike_isakmp_header *isakmp) { Ipike_payload_header *payload; Ip_u8 this_payload; Ipike_error err; Ipike_payload_enum ctx; /* Process payloads */ this_payload = isakmp->next_payload; payload = ipike_first_payload(isakmp, &ctx); err = IPIKE_SUCCESS; while (payload != IP_NULL) { switch (this_payload) { case IPIKE_PAYLOAD_SECURITY_ASSOCIATION: /* RFC2409 Section 5, * The SA payload MUST precede all other payloads in a * phase 1 exchange. */ if (IPIKE_PAYLOAD_SECURITY_ASSOCIATION != isakmp->next_payload) return IPIKE_WRONG_PAYLOAD; if (ie->ike_sa->is_initiator) /* Free the SA that was sent to the responder */ ipike_sa_free(&ie->ike_sa->sa, IP_NULL); else { err = ipike_aggressive_mode_store_sai_b( &ie->ike_sa->sai_b, (Ipike_sa_payload*) payload); /* Store the binary encoding of the SA from the initiator */ if (IPIKE_SUCCESS != err) break; } err = ipike_sa_extract(ie, (Ipike_sa_payload*) payload, &ie->ike_sa->sa); break; case IPIKE_PAYLOAD_KEY_EXCHANGE: err = ipike_key_exchange_extract((Ipike_ke_payload*) payload, ie->ike_sa->is_initiator ? &ie->ike_sa->g_xr : &ie->ike_sa->g_xi); break; case IPIKE_PAYLOAD_NONCE: err = ipike_payload_nonce_extract((Ipike_nonce_payload*) payload, ie->ike_sa->is_initiator ? &ie->ike_sa->nr : &ie->ike_sa->ni); break; case IPIKE_PAYLOAD_IDENTFICATION: err = ipike_identification_ike_extract((Ipike_id_payload*) payload, ie->ike_sa->sa.doi, ie->ike_sa->is_initiator ? &ie->ike_sa->idir : &ie->ike_sa->idii); break; case IPIKE_PAYLOAD_HASH: err = ipike_hash_extract((Ipike_hash_payload*) payload, ie->ike_sa->is_initiator ? &ie->ike_sa->hash_r : &ie->ike_sa->hash_i); break; case IPIKE_PAYLOAD_NOTIFICATION: err = ipike_notification_process_message( ie, (Ipike_notification_payload*) payload); break; case IPIKE_PAYLOAD_CERTIFICATE: err = ipike_payload_certificate_extract( (Ipike_cert_payload*) payload, &ie->ike_sa->cert); break; case IPIKE_PAYLOAD_CERTIFICATE_REQUEST: ie->certificate_requested = IP_TRUE; err = ipike_payload_certificate_req_extract_v1( (Ipike_cert_req_payload*) payload, &ie->ike_sa->cert); break; case IPIKE_PAYLOAD_SIGNATURE: err = ipike_sign_extract((Ipike_sign_payload*) payload, ie->ike_sa->is_initiator ? &ie->ike_sa->sign_r : &ie->ike_sa->sign_i); break; case IPIKE_PAYLOAD_VENDOR_ID: err = ipike_payload_vendor_id_process( ie->ike_sa, (Ipike_vendor_id_payload*) payload); break; case IPIKE_PAYLOAD_NAT_DISCOVERY: err = ipike_nat_discovery_process( ie->ike_sa, (Ipike_nat_discovery_payload*) payload); break; default: IPCOM_LOG2(ERR, "ipike_aggressive_mode_process_payloads() :: "\ "'%s' (%d) is an unsupported payload type", ipike_payload_type_to_string(this_payload), this_payload); err = IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD; break; } if (err != IPIKE_SUCCESS) break; this_payload = payload->next_payload; payload = ipike_next_payload(&ctx); } ipike_free_payload_enumerator(&ctx); if (err != IPIKE_SUCCESS) { IPIKE_EVENT_LOG(IKE_PACKET_DISCARD, ISAKMP_PACKET_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } return ipike_aggressive_mode_update_state(ie); } /* *=========================================================================== * ipike_aggressive_mode_add_reply_payloads *=========================================================================== */ IP_PUBLIC Ipike_error ipike_aggressive_mode_add_reply_payloads( Ipike_isakmp_exchange* ie, Ipike_payload_header*** reply_payloads) { Ipike_error err = IPIKE_SUCCESS; const Ip_u16* payload_ids = IP_NULL; int i = 0; Ipike_transform_ike *transform_ike; payload_ids = ipike_aggressive_mode_get_payload_order(ie); ip_assert(payload_ids != IP_NULL); for (i = 0; payload_ids[i] != IPIKE_PAYLOAD_NONE; i++) { Ipike_payload_header* reply_payload = IP_NULL; Ip_u8 payload_type; if (IP_BIT_ISSET(payload_ids[i], IPIKE_PAYLOAD_OPT) && IP_BIT_ISSET(payload_ids[i], IPIKE_PAYLOAD_ADD) == IP_FALSE) /* Only add the optional payload that had the IPIKE_PAYLOAD_ADD bit set */ continue; payload_type = (Ip_u8) payload_ids[i]; switch (payload_type) { case IPIKE_PAYLOAD_SECURITY_ASSOCIATION: err = ipike_sa_create(&ie->ike_sa->sa, (Ipike_sa_payload**) &reply_payload); if (err == IPIKE_SUCCESS && ie->ike_sa->is_initiator) { err = ipike_aggressive_mode_store_sai_b(&ie->ike_sa->sai_b, (Ipike_sa_payload*) reply_payload); if (err != IPIKE_SUCCESS) ipcom_free(reply_payload); } break; case IPIKE_PAYLOAD_KEY_EXCHANGE: err = ipike_key_exchange_create(ie->ike_sa->is_initiator ? &ie->ike_sa->g_xi : &ie->ike_sa->g_xr, (Ipike_ke_payload**) &reply_payload); break; case IPIKE_PAYLOAD_IDENTFICATION: err = ipike_identification_create(ie->ike_sa->is_initiator ? &ie->ike_sa->idii : &ie->ike_sa->idir, (Ipike_id_payload**) &reply_payload); break; case IPIKE_PAYLOAD_HASH: err = ipike_hash_create(ie->ike_sa->is_initiator ? &ie->ike_sa->hash_i : &ie->ike_sa->hash_r, (Ipike_hash_payload**) &reply_payload); break; case IPIKE_PAYLOAD_NONCE: err = ipike_payload_nonce_create(ie->ike_sa->is_initiator ? &ie->ike_sa->ni : &ie->ike_sa->nr, (Ipike_nonce_payload**) &reply_payload); break; case IPIKE_PAYLOAD_CERTIFICATE: err = ipike_aggressive_mode_cert_create(ie->ike_conf, (Ipike_cert_payload**) &reply_payload); break; case IPIKE_PAYLOAD_SIGNATURE: err = ipike_sign_create(ie->ike_sa->is_initiator ? &ie->ike_sa->sign_i : &ie->ike_sa->sign_r, (Ipike_sign_payload**) &reply_payload); break; case IPIKE_PAYLOAD_VENDOR_ID: if ((IPIKE_SUCCESS == err) && (ipike.port_nat != 0)) { err = ipike_payload_vendor_id_create(IPIKE_VENDOR_ID_NAT_T, (Ipike_vendor_id_payload**) &reply_payload); if (IPIKE_SUCCESS == err) { err = ipike_array_add((void***) reply_payloads, reply_payload); if (IPIKE_SUCCESS != err) ipcom_free(reply_payload); } } if (IPIKE_SUCCESS == err) { err = ipike_payload_vendor_id_create(IPIKE_VENDOR_ID_DPD, (Ipike_vendor_id_payload**) &reply_payload); if (IPIKE_SUCCESS == err) { err = ipike_array_add((void***) reply_payloads, reply_payload); if (IPIKE_SUCCESS != err) ipcom_free(reply_payload); } } reply_payload = IP_NULL; break; case IPIKE_PAYLOAD_NAT_DISCOVERY: /* Always two payloads (local and peer) */ transform_ike = ipike_transform_ike_from_exch(ie); if (transform_ike==IP_NULL) { err=IPIKE_FAILED; break; } err = ipike_nat_discovery_create(&ie->ike_sa->local_addr, ie->ike_sa->initiator_cookie, ie->ike_sa->responder_cookie, transform_ike->hash_algorithm, (Ipike_nat_discovery_payload**) &reply_payload); if (IPIKE_SUCCESS == err) err = ipike_array_add((void***) reply_payloads, reply_payload); if (IPIKE_SUCCESS == err) { err = ipike_nat_discovery_create(&ie->ike_sa->peer_addr, ie->ike_sa->initiator_cookie, ie->ike_sa->responder_cookie, transform_ike->hash_algorithm, (Ipike_nat_discovery_payload**) &reply_payload); } break; case IPIKE_PAYLOAD_CERTIFICATE_REQUEST: /* Request certificate if do not already have the peers certificate */ if ( !ie->ike_sa->cert.peer ) err = ipike_main_mode_add_cert_request(ie->ike_conf, reply_payloads); break; case IPIKE_PAYLOAD_NOTIFICATION: case IPIKE_PAYLOAD_DELETE: IPCOM_LOG1(ERR, "Payload creation for '%s' is not implemented", ipike_payload_type_to_string(payload_type)); err = IPIKE_NOT_IMPLEMENTED; goto error; default: IPCOM_LOG1(ERR, "Payload creation failed since %d is a unknown payload type", payload_type); err = IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD; goto error; } if (err != IPIKE_SUCCESS) goto error; if (reply_payload != IP_NULL) { if (IPIKE_SUCCESS != (err = ipike_array_add((void***) reply_payloads, reply_payload))) { ipcom_free(reply_payload); goto error; } } } return IPIKE_SUCCESS; error: ipike_array_free((void**) *reply_payloads, ipcom_free); /*lint !e123 */ *reply_payloads = IP_NULL; return err; } /* *=========================================================================== * ipike_aggressive_mode_cleartext_outgoing_message *=========================================================================== */ IP_PUBLIC Ipike_error ipike_aggressive_mode_cleartext_outgoing_message( Ipike_isakmp_exchange* ie, Ipike_isakmp_header** outgoing_isakmp) { (void) ie; (void) outgoing_isakmp; return IPIKE_SUCCESS; } /* *=========================================================================== * ipike_aggressive_mode_exchange_done *=========================================================================== */ IP_PUBLIC Ipike_error ipike_aggressive_mode_exchange_done(Ipike_isakmp_exchange* ie) { Ipike_error err; ipike_sadb_free_intermediate(ie->ike_sa); if (IPIKE_SUCCESS != (err = ipike_cpy_value(&ie->ike_sa->base_iv, &ie->iv))) return err; if (IPIKE_SUCCESS != (err = ipike_sadb_set_state(ie, ie->ike_sa, IPIKE_SA_ACTIVE))) return err; /* Set liveness */ ie->ike_sa->liveness.timeout = (Ip_u32) ie->ike_conf->liveness; ipcom_microtime(&ie->stop); IPCOM_LOG3(INFO, "Aggressive mode exchange done in %d ms (peer: %s, Message ID: %d)", (ie->stop.tv_sec - ie->start.tv_sec) * 1000 + (ie->stop.tv_usec - ie->start.tv_usec) / 1000, ipike_addr_to_str(&ie->ike_sa->peer_addr), ie->message_id); (void)ipike_print_memory(IPCOM_LOG_DEBUG, "Final phase 1 (aggressive mode) IV: ", ie->iv.value, ie->iv.len); if (ie->ike_conf->initial_contact && (ie->rekey_spi.len == 0)) ipike_informational_report_initial_contact(ie->ike_sa); /* Initiate a quick mode exchange if we are the initiator and * if option1 (only IKE) is not set */ if (ie->ike_sa->is_initiator && !ie->option1) (void)ipike_isakmp_initiate_ipsec_exchanges(ie->ike_sa, IP_NULL, ie->option2); return IPIKE_SUCCESS; } #endif /* IPIKE_USE_AGGRESSIVE_MODE */ /* **************************************************************************** * END OF FILE **************************************************************************** */