/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_exchange_main_mode.c,v $ $Revision: 1.33.10.13 $ * $Source: /home/interpeak/CVSRoot/ipike/src/ipike_exchange_main_mode.c,v $ * $Author: hxu0 $ $Date: 2015-07-13 08:20:47 $ * $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_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 "ipike_http_fetcher.h" #include #include #include #include #include /* **************************************************************************** * 4 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 5 DEFINES **************************************************************************** */ /* **************************************************************************** * 6 TYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* *=========================================================================== * ipike_main_mode_update_state *=========================================================================== * Description: Updates the exchange state after the data from * message #1, 2, 3, 4, 5 or 6 * has been stored. * Parameters: ie - holds all the states associated with the exchange. * Returns: IPIKE_SUCCESS * IPIKE_OUT_OF_MEMORY * IPIKE_KE_DH_ERROR * */ IP_STATIC Ipike_error ipike_main_mode_update_after_msg_1(Ipike_isakmp_exchange* ie); IP_STATIC Ipike_error ipike_main_mode_update_after_msg_2(Ipike_isakmp_exchange* ie); IP_STATIC Ipike_error ipike_main_mode_update_after_msg_3(Ipike_isakmp_exchange* ie); IP_STATIC Ipike_error ipike_main_mode_update_after_msg_4(Ipike_isakmp_exchange* ie); IP_STATIC Ipike_error ipike_main_mode_update_after_msg_5(Ipike_isakmp_exchange* ie); IP_STATIC Ipike_error ipike_main_mode_update_after_msg_6(Ipike_isakmp_exchange* ie); /* *=========================================================================== * ipike_main_mode_update_state *=========================================================================== * Description: Calls functions that updates necessary state paramters during * phase 1 main mode exchange. * Parameters: ie - holds all the states associated with the exchange. * Returns: IPIKE_SUCCESS * IPIKE_OUT_OF_MEMORY * IPIKE_KE_DH_ERROR * */ IP_STATIC Ipike_error ipike_main_mode_update_state(Ipike_isakmp_exchange* ie); /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipike_main_mode_initialize_id *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_initialize_id( Ipike_isakmp_exchange* ie, Ipike_id* id) { Ipike_error err = IPIKE_SUCCESS; const char* str = ie->ike_conf->local_id; /* Try to use id from configuration, use IP-address if fails */ if (IP_NULL == str || IPIKE_SUCCESS != ipike_identification_generate(str, id)) { err = ipike_ipsec_set_idix(&ie->ike_sa->local_addr, id); } return err; } /* This IKE daemon is responder */ /* *=========================================================================== * ipike_main_mode_update_after_msg_1 *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_after_msg_1(Ipike_isakmp_exchange* ie) { Ipike_error err; err = ipike_policy_select_ike_sa_param(ie->ike_conf, &ie->ike_sa->sa, &ie->ike_sa->selected, IP_FALSE); if ( err != IPIKE_SUCCESS ) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, PROPOSAL_MISMATCH, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } return IPIKE_SUCCESS; } /* *=========================================================================== * ipike_main_mode_update_after_msg_3 *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_after_msg_3(Ipike_isakmp_exchange* ie) { Ipike_error err; Ipike_sadb_entry *ike_sa = ie->ike_sa; Ipike_transform_ike *transform = ipike_transform_ike_from_exch(ie); if (transform==IP_NULL) return IPIKE_FAILED; if (IPIKE_SUCCESS != (err = ipike_payload_nonce_generate(&ike_sa->nr))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_generate_dh_key(transform->dh_prime, transform->dh_generator, &ie->dh, &ike_sa->g_xr))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key(ie->dh, &ike_sa->g_xi, &ike_sa->g_xy))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid(ie->ike_conf, ike_sa))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv(ike_sa, &ie->iv))) goto errout; return IPIKE_SUCCESS; errout: IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ike_sa->peer_addr, &ike_sa->local_addr, 0, IP_NULL); return err; } /* *=========================================================================== * ipike_main_mode_update_after_msg_5 *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_after_msg_5(Ipike_isakmp_exchange* ie) { Ipike_error err; Ipike_sadb_entry* ike_sa = ie->ike_sa; Ip_u16 auth_meth; Ip_u16 hash_alg; Ipike_transform_ike *transform_ike; /* Check if there is a more suitable IKE SA config */ ipike_main_mode_update_responder_config(ie); if (IPIKE_SUCCESS != (err = ipike_main_mode_authentication_check(ie))) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, AUTHENTICATION_ERROR, &ike_sa->peer_addr, &ike_sa->local_addr, 0, IP_NULL); return err; } switch (ike_sa->sa.doi) { case IPIKE_DOI_IPSEC: if (IPIKE_SUCCESS != (err = ipike_main_mode_initialize_id(ie, &ike_sa->idir))) goto errout; break; default: IPCOM_LOG1(ERR, "ipike_main_mode_update_after_msg_5() :: "\ "the DOI %d is not supported", ike_sa->sa.doi); err = IPIKE_DOI_UNSUPPORTED; goto errout; } transform_ike = ipike_transform_ike_from_exch(ie); if (transform_ike==IP_NULL) { err = IPIKE_FAILED; goto errout; } auth_meth = transform_ike->authentication_method; if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES) hash_alg = IPIKE_ATTR_HASH_SHA1; else hash_alg = transform_ike->hash_algorithm; err = ipike_crypto_compute_hash_r(hash_alg, ike_sa, &ike_sa->hash_r); if ( err != IPIKE_SUCCESS ) goto errout; 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, &ike_sa->hash_r, &ike_sa->sign_r); 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, &ike_sa->hash_r, &ike_sa->sign_r); /* Everything should be encrypted from now on */ ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION; errout: if ( err != IPIKE_SUCCESS ) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ike_sa->peer_addr, &ike_sa->local_addr, 0, IP_NULL); return err; } return IPIKE_SUCCESS; } /* This IKE daemon is initiator */ /* *=========================================================================== * ipike_main_mode_update_before_msg_1 *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_before_msg_1(Ipike_isakmp_exchange* ie) { Ipike_error err; err = ipike_sa_ike_initialize(ie->ike_conf, &ie->ike_sa->sa); if ( err != IPIKE_SUCCESS ) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ie->ike_sa->local_addr, &ie->ike_sa->peer_addr, 0, IP_NULL); return err; } return IPIKE_SUCCESS; } /* *=========================================================================== * ipike_main_mode_update_after_msg_2 *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_after_msg_2(Ipike_isakmp_exchange* ie) { Ipike_error err; Ipike_sadb_entry* ike_sa = ie->ike_sa; Ipike_transform_ike* transform; err = ipike_policy_select_ike_sa_param(ie->ike_conf, &ike_sa->sa, &ie->ike_sa->selected, IP_TRUE); if (IPIKE_SUCCESS != err) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, PROPOSAL_MISMATCH, &ike_sa->peer_addr, &ike_sa->local_addr, 0, IP_NULL); return err; } transform = ipike_transform_ike_from_exch(ie); /* We should have a selected transform here otherwise would * ipike_policy_select_ike_sa_param failed */ ip_assert(transform != IP_NULL); err = ipike_crypto_generate_dh_key(transform->dh_prime, transform->dh_generator, &ie->dh, &ike_sa->g_xi); if (IPIKE_SUCCESS != err) goto errout; err = ipike_payload_nonce_generate(&ike_sa->ni); errout: if (IPIKE_SUCCESS != err) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ike_sa->peer_addr, &ike_sa->local_addr, 0, IP_NULL); } return err; } /* *=========================================================================== * ipike_main_mode_update_after_msg_4 *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_after_msg_4(Ipike_isakmp_exchange* ie) { Ipike_error err; Ipike_sadb_entry* ike_sa = ie->ike_sa; Ip_u16 auth_meth; Ip_u16 hash_alg; Ipike_transform_ike *transform_ike; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_dh_key(ie->dh, &ike_sa->g_xr, &ike_sa->g_xy))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_skeyid(ie->ike_conf, ike_sa))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_phase1_secret_key(ie))) goto errout; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_initial_phase1_iv(ike_sa, &ie->iv))) goto errout; switch (ike_sa->sa.doi) { case IPIKE_DOI_IPSEC: if (IPIKE_SUCCESS != (err = ipike_main_mode_initialize_id(ie, &ike_sa->idii))) goto errout; break; default: IPCOM_LOG1(ERR, "ipike_main_mode_update_after_msg_4() ::"\ " the DOI %d is not supported", ike_sa->sa.doi); err = IPIKE_DOI_UNSUPPORTED; goto errout; } transform_ike = ipike_transform_ike_from_exch(ie); if (transform_ike==IP_NULL) { err= IPIKE_FAILED; goto errout; } auth_meth = transform_ike->authentication_method; if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES) hash_alg = IPIKE_ATTR_HASH_SHA1; else hash_alg = transform_ike->hash_algorithm; if (IPIKE_SUCCESS != (err = ipike_crypto_compute_hash_i(hash_alg, ike_sa, &ike_sa->hash_i))) goto errout; 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, &ike_sa->hash_i, &ike_sa->sign_i); 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, &ike_sa->hash_i, &ike_sa->sign_i); /* Everything should be encrypted from now on */ ie->isakmp_flags = IPIKE_ISAKMP_ENCRYPTION; errout: if ( err != IPIKE_SUCCESS ) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, IKE_INTERNAL_ERROR, &ike_sa->peer_addr, &ike_sa->local_addr, 0, IP_NULL); return err; } return IPIKE_SUCCESS; } /* *=========================================================================== * ipike_main_mode_update_after_msg_6 *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_after_msg_6(Ipike_isakmp_exchange* ie) { Ipike_error err; err = ipike_main_mode_authentication_check(ie); if ( err != IPIKE_SUCCESS ) { IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, AUTHENTICATION_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } return IPIKE_SUCCESS; } /* *=========================================================================== * ipike_main_mode_update_state *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_update_state(Ipike_isakmp_exchange* ie) { switch (ie->message_number) { /* We are responder */ case 1: return ipike_main_mode_update_after_msg_1(ie); case 3: return ipike_main_mode_update_after_msg_3(ie); case 5: return ipike_main_mode_update_after_msg_5(ie); /* We are initiator */ case 0: return ipike_main_mode_update_before_msg_1(ie); case 2: return ipike_main_mode_update_after_msg_2(ie); case 4: return ipike_main_mode_update_after_msg_4(ie); case 6: return ipike_main_mode_update_after_msg_6(ie); } IPCOM_LOG1(ERR, "IKE main mode has 6 messages, this was %d", ie->message_number); IPIKE_EVENT_LOG(IKE_PHASE_I_FAIL, ISAKMP_PACKET_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return IPIKE_INVALID_MESSAGE_NUMBER; } /* *=========================================================================== * ipike_main_mode_store_sai_b *=========================================================================== */ IP_STATIC Ipike_error ipike_main_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_main_mode_cert_create *=========================================================================== */ IP_STATIC Ipike_error ipike_main_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; } /* *=========================================================================== * ipike_main_mode_verify_auth *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_verify_auth(Ipike_isakmp_exchange *ie) { Ipike_sadb_entry *ike_sa = ie->ike_sa; Ipike_transform_ike *transform = IP_NULL; Ipike_error err = IPIKE_AUTHENTICATION_FAILED; Ip_u16 auth_meth = 0; Ip_u16 hash_alg = 0; ip_assert(ike_sa); transform = ipike_transform_ike_from_exch(ie); if (transform == IP_NULL) { IPCOM_LOG0(ERR, "ipike_main_mode_verify_auth :: null transform"); goto error; } auth_meth = transform->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; /* Compute hash for RSA and DSS */ if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES || auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES ) { if (ike_sa->is_initiator) err = ipike_crypto_compute_hash_r(hash_alg, ike_sa, &ike_sa->hash_r); else err = ipike_crypto_compute_hash_i(hash_alg, ike_sa, &ike_sa->hash_i); if (err != IPIKE_SUCCESS) goto error; } /* Verify signature */ if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES) { err = ipike_crypto_verify_dsa_sign(ike_sa->cert.peer, ike_sa->is_initiator ? &ike_sa->hash_r : &ike_sa->hash_i, ike_sa->is_initiator ? &ike_sa->sign_r : &ike_sa->sign_i); } else if ( auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES ) { err = ipike_crypto_verify_rsa_sign(ike_sa->cert.peer, ike_sa->is_initiator ? &ike_sa->hash_r : &ike_sa->hash_i, ike_sa->is_initiator ? &ike_sa->sign_r : &ike_sa->sign_i); } else { if (ike_sa->is_initiator) err = ipike_crypto_verify_hash_r(ie->ike_sa); else err = ipike_crypto_verify_hash_i(ie->ike_sa); } error: return err; } /* *=========================================================================== * ipike_main_mode_http_get_crl_cb *=========================================================================== */ IP_STATIC void ipike_main_mode_http_get_crl_cb( Ipike_error status, const char *data, Ip_size_t data_len, void *id) { Ipike_isakmp_exchange *ie = IP_NULL; X509_CRL *crl = IP_NULL; X509_CRL** crls = IP_NULL; X509** trusted = IP_NULL; X509** ca = IP_NULL; Ipike_sadb_entry* ike_sa = IP_NULL; Ipike_error err = IPIKE_AUTHENTICATION_FAILED; ip_assert(id); /* Get exchange state using the unique id */ ie = ipike_isakmp_get_exchange_from_unique_id(id, ipike_isakmp_get_unique_id_size()); if ( !ie ) { /* No exchange found => abort */ IPCOM_LOG0(ERR, "ipike_main_mode_http_get_crl_cb()"\ " :: no IKE exchange state found"); /* Free allocated id */ ipcom_free( id ); /* No exchange found, stop proccessing */ return; } /* We should always have a valid ike_sa here */ ip_assert(ie->ike_sa); ike_sa = ie->ike_sa; /* Was the HTTP request successful */ if ( IPIKE_SUCCESS != status ) { IPCOM_LOG1(ERR, "ipike_main_mode_http_get_crl_cb() ::"\ " bad http response received (%d)", status); goto done_continue; } /* Decode CRL */ crl = ipike_crypto_decode_crl((Ip_u8 *)data, data_len); if ( !crl ) { IPCOM_LOG0(ERR, "ipike_main_mode_http_get_crl_cb() :: failed to decode crl"); goto done_continue; } /* Add CRL to CRL list */ if ( IPIKE_SUCCESS != ipike_array_add((void***) &crls, crl) ) goto done_continue; /* Get intermediate CA certs from local storage */ ca = ipike_crypto_get_intermediate_ca_certs( &ike_sa->cert, ie->ike_conf->authentication.intermediate_ca_store); /* Get trusted CA certs from local storage */ trusted = ipike_crypto_get_trusted_certs( ie->ike_conf->authentication.trusted_ca_store); /* Must at least have one trusted CA */ if ( !trusted ) { IPCOM_LOG0(ERR, "ipike_main_mode_http_get_crl_cb() ::"\ " failed to read trusted certificate"); goto done_continue; } #ifdef IPIKE_USE_OCSP /* IKEv1 doesnt support OCSP define necessary for avoiding code duplication */ err = ipike_crypto_verify_certificate_ocsp(trusted, ca, ike_sa->cert.peer, crls, IP_NULL); #else err = ipike_crypto_verify_certificate(trusted, ca, ike_sa->cert.peer, crls); #endif done_continue: /* Free allocated id */ ipcom_free( id ); ipike_array_free((void**) trusted, (void(*)(void*)) X509_free); ipike_array_free((void**) ca, (void(*)(void*)) X509_free); ipike_array_free((void**) crls, (void(*)(void*)) X509_CRL_free); /* Update error state of IKE SA */ ie->ike_sa->error = err; /* On failure */ if ( err != IPIKE_SUCCESS ) { IPCOM_LOG0(ERR, "ipike_main_mode_http_get_crl_cb() ::"\ " certificate verification failed"); (void)ipike_informational_report_error(ie->ike_sa, IP_NULL, err); /* Set IKE SA to dying */ ipike_sadb_set_state(ie, ie->ike_sa, IPIKE_SA_DYING); /* Destroy this exchange */ ipike_isakmp_free_exchange(ie, IP_TRUE); } else { /* Continue the exchange and send the response */ ipike_isakmp_process_message_continue(ie); } } /* *=========================================================================== * ipike_main_mode_http_get *=========================================================================== */ IP_STATIC Ipike_error ipike_main_mode_http_get( Ipike_isakmp_exchange *ie, const char *uri, Ipike_http_fetcher_callback callback) { Ip_u8 *id; Ip_u32 id_len; if ( !uri ) return IPIKE_FAILED; id_len = ipike_isakmp_get_unique_id_size(); id = ipcom_malloc( id_len ); if ( !id ) { IP_PANIC(); return IPIKE_OUT_OF_MEMORY; } memset( id, 0, id_len); /* Create an unique id for this exchange that is used for obtaining correct exchange state in the callback */ if ( !ipike_isakmp_get_unique_id_for_exchange(ie, id, &id_len)) goto error_out; /* Get data that is pointed out by the URI */ if ( IPIKE_SUCCESS != ipike_http_fetcher_get(uri, callback, id) ) { IPCOM_LOG1(ERR, "ipike_main_mode_http_get :: failed to fetch \"%s\"", uri); goto error_out; } /* Mark that this exchange is waiting for an external response */ ie->wait_response = IP_TRUE; return IPIKE_SUCCESS; error_out: ipcom_free(id); return IPIKE_FAILED; } /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipike_main_mode_cert_req_create *=========================================================================== */ IP_PUBLIC Ipike_error ipike_main_mode_add_cert_request( Ipike_config_ike_sa* conf, Ipike_payload_header*** reply_payloads) { Ipike_cert_req_payload* payload = IP_NULL; X509** trusted = IP_NULL; X509** iter = IP_NULL; Ipike_error err = IPIKE_SUCCESS; /* Get trusted CA certs from local storage */ trusted = ipike_crypto_get_trusted_certs(conf->authentication.trusted_ca_store); /* Create a certificate request payload for each trusted CA */ for (iter = trusted; iter && *iter; iter++) { payload = IP_NULL; err = ipike_payload_certificate_req_create_v1(&payload, *iter); if ( err != IPIKE_SUCCESS ) goto errout; /* Add the payload if we have constructed on*/ if ( payload ) { err = ipike_array_add((void***) reply_payloads, payload); if (IPIKE_SUCCESS != err) { ipcom_free(payload); goto errout; } } } errout: ipike_array_free((void**) trusted, (void(*)(void*)) X509_free); return err; } /* *=========================================================================== * ipike_main_mode_update_responder_config *=========================================================================== */ IP_PUBLIC void ipike_main_mode_update_responder_config(Ipike_isakmp_exchange *ie) { Ipike_sadb_entry* ike_sa; Ipike_config_ike_sa *ike_conf; Ipike_id* id; ike_sa = ie->ike_sa; id = &ike_sa->idii; ike_conf = ipike_config_get_ike_sa_from_address_and_remote_id(ie, &ie->msg.local_addr, &ie->msg.peer_addr, id->id_type, &id->id_data, ike_sa->cert.peer); if ( IP_NULL != ike_conf && ike_conf != ie->ike_conf ) { /* We found a differnet configuration that can be used */ ie->ike_conf = ike_conf; /* Update IKE SA parameters */ if ( IP_NULL != ike_sa->id ) ipcom_free(ike_sa->id); ike_sa->id = ipcom_strdup( ike_conf->ike_id ); IPCOM_LOG0(NOTICE, "ipike_main_mode_update_responder_config :: Updated IKE SA config selection based on 'remote_identifier'"); } /* Fall through even if no matching configuration was found since and * let the negotiation fail in the authentication check */ } /* *=========================================================================== * ipike_main_mode_authentication_check *=========================================================================== */ IP_GLOBAL Ipike_error ipike_main_mode_authentication_check(Ipike_isakmp_exchange* ie) { Ipike_error err; Ip_u16 auth_meth; Ipike_transform_ike *transform; Ipike_sadb_entry* ike_sa = ie->ike_sa; X509** trusted = IP_NULL; X509** ca = IP_NULL; X509_CRL** crls = IP_NULL; Ipike_id* id; if (ike_sa->is_initiator) id = &ike_sa->idir; else id = &ike_sa->idii; /* Do we allow the remote peer access */ err = ipike_policy_accept_id(ie->ike_conf->remote_id, id->id_type, &id->id_data, ike_sa->cert.peer); if (err != IPIKE_SUCCESS) { IPCOM_LOG1(ERR, "ipike_main_mode_authentication_check() ::"\ " bad 'remote_identifier', err = %d", err); goto error; } /* Authenticate */ err = ipike_main_mode_verify_auth(ie); if (err != IPIKE_SUCCESS) { IPCOM_LOG1(ERR, "ipike_main_mode_authentication_check() ::"\ " failed to verify authentication data, err = %d", err); goto error; } transform = ipike_transform_ike_from_exch(ie); if (transform == IP_NULL) { IPCOM_LOG0(ERR, "ipike_main_mode_authentication_check() ::"\ " null transform"); goto error; } auth_meth = transform->authentication_method; if (auth_meth == IPIKE_ATTR_AUTH_DSS_SIGNATURES || auth_meth == IPIKE_ATTR_AUTH_RSA_SIGNATURES) { /* Check if a remote (HTTP) location of CRL is configured */ if ( ie->ike_conf->authentication.crl_store && ipcom_strncmp(ie->ike_conf->authentication.crl_store, "http://", 7) == 0 ) { /* Fetching CRLs using CRL using http */ IPCOM_LOG1(DEBUG2, "ipike_main_mode_authentication_check() ::"\ " fetching crl via http \"%s\"", ie->ike_conf->authentication.crl_store ); /* Verify certificate when we have received the CRL in the callback */ err = ipike_main_mode_http_get(ie, ie->ike_conf->authentication.crl_store, ipike_main_mode_http_get_crl_cb); /* Failed to fetch CRL */ if ( IPIKE_SUCCESS != err ) { err = IPIKE_AUTHENTICATION_FAILED; IPCOM_LOG0(ERR, "ipike_main_mode_authentication_check() ::"\ " failed to fetch crl via http"); goto error; } /* Fetching CRLs via HTTP, break processing for now and continue * when we have received the certificate */ return err; } else { ca = ipike_crypto_get_intermediate_ca_certs( &ike_sa->cert, ie->ike_conf->authentication.intermediate_ca_store); trusted = ipike_crypto_get_trusted_certs( ie->ike_conf->authentication.trusted_ca_store); crls = ipike_crypto_read_crls(ie->ike_conf->authentication.crl_store); if (trusted == IP_NULL) { IPCOM_LOG0(ERR, "ipike_main_mode_authentication_check() ::"\ " failed to read trusted certificate"); err = IPIKE_INVALID_VALUE; goto error; } #ifdef IPIKE_USE_OCSP /* IKEv1 doesnt support OCSP define necessary for avoiding code * duplication */ err = ipike_crypto_verify_certificate_ocsp(trusted, ca, ike_sa->cert.peer, crls, IP_NULL); #else err = ipike_crypto_verify_certificate(trusted, ca, ike_sa->cert.peer, crls); #endif if (err != IPIKE_SUCCESS) { IPCOM_LOG0(ERR, "ipike_main_mode_update_after_msg_6: certificate verification failed"); goto error; } } } error: ipike_array_free((void**) trusted, (void(*)(void*)) X509_free); ipike_array_free((void**) ca, (void(*)(void*)) X509_free); ipike_array_free((void**) crls, (void(*)(void*)) X509_CRL_free); if (err) { /* Send a response and then destroy this exchange */ ie->send_and_destroy = IP_TRUE; } return err; } /* *=========================================================================== * ipike_main_mode_on_new_exchange_initiator *=========================================================================== */ IP_PUBLIC Ipike_error ipike_main_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_main_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_main_mode_update_state(ie); } /* *=========================================================================== * ipike_main_mode_on_new_exchange_responder *=========================================================================== */ IP_PUBLIC Ipike_error ipike_main_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_main_mode_on_new_exchange: 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_main_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_main_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_main_mode_on_delete_exchange *=========================================================================== */ IP_PUBLIC void ipike_main_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_main_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_main_mode_get_payload_order *=========================================================================== */ IP_PUBLIC const Ip_u16 * ipike_main_mode_get_payload_order(Ipike_isakmp_exchange* ie) { /* All authentication methods has #1 and #2 equal and the authentication method can not be known by the responder before processing #1 */ static Ip_u16 before_first_sa_processed[] = { /* message # 1 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 2 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 3 */ IPIKE_PAYLOAD_NONE, /* message # 4 */ IPIKE_PAYLOAD_NONE, /* message # 5 */ IPIKE_PAYLOAD_NONE, /* message # 6 */ IPIKE_PAYLOAD_NONE, }; static Ip_u16 pre_shared_keys_payloads[] = { /* message # 1 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 2 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 3 */ IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_NONE, /* message # 4 */ IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_NONE, /* message # 5 */ IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 6 */ IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, }; static Ip_u16 public_keys_sign_payloads[] = { /* message # 1 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST, IPIKE_PAYLOAD_NONE, /* message # 2 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST, IPIKE_PAYLOAD_NONE, /* message # 3 */ IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST, IPIKE_PAYLOAD_NONE, /* message # 4 */ IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_CERTIFICATE_REQUEST, IPIKE_PAYLOAD_NONE, /* message # 5 */ IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD, IPIKE_PAYLOAD_SIGNATURE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_CERTIFICATE_REQUEST, IPIKE_PAYLOAD_NONE, /* message # 6 */ IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_CERTIFICATE | IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD, IPIKE_PAYLOAD_SIGNATURE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NOTIFICATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE_REQUEST, IPIKE_PAYLOAD_NONE, }; static Ip_u16 public_keys_encrypt_payloads[] = { /* message # 1 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 2 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 3 */ IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_NONE, /* message # 4 */ IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_NONE, /* message # 5 */ IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 6 */ IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, }; static Ip_u16 rev_public_keys_encrypt_payloads[] = { /* message # 1 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 2 */ IPIKE_PAYLOAD_SECURITY_ASSOCIATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_ADD | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 3 */ IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_CERTIFICATE, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_NONE, /* message # 4 */ IPIKE_PAYLOAD_NONCE, IPIKE_PAYLOAD_KEY_EXCHANGE, IPIKE_PAYLOAD_IDENTFICATION, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_NAT_DISCOVERY, IPIKE_PAYLOAD_NONE, /* message # 5 */ IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, /* message # 6 */ IPIKE_PAYLOAD_HASH, IPIKE_PAYLOAD_OPT | IPIKE_PAYLOAD_VENDOR_ID, IPIKE_PAYLOAD_NONE, }; static Ip_u16 *id_prot_payloads[] = { before_first_sa_processed, pre_shared_keys_payloads, public_keys_sign_payloads, public_keys_sign_payloads, public_keys_encrypt_payloads, rev_public_keys_encrypt_payloads }; int i = 1; int message_nr = ie->message_number; Ip_u16 * ret; Ip_u16 n = 0; Ip_u16 auth_method = 0; if (ipike_transform_ike_from_exch(ie) != IP_NULL) auth_method = ipike_transform_ike_from_exch(ie)->authentication_method; if (auth_method > IPIKE_ATTR_AUTH_COUNT) return IP_NULL; ret = id_prot_payloads[auth_method]; i = 1; while (i != message_nr) if (*ret++ == IPIKE_PAYLOAD_NONE) i++; /* Some optional must be added if we are using 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); } /* Check policy for sending certificate and certificate request */ if ( auth_method != IPIKE_ATTR_AUTH_PRE_SHARED_KEY ) { if ( n == 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); } else if ( n == 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); } } i++; } return ret; } /* *=========================================================================== * ipike_main_mode_process_payloads *=========================================================================== */ IP_PUBLIC Ipike_error ipike_main_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 { /* Store the binary encoding of the SA from the initiator */ err = ipike_main_mode_store_sai_b(&ie->ike_sa->sai_b, (Ipike_sa_payload*) payload); 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_main_mode_process_payloads() ::"\ " '%s' (%d) is an unsupported payload type", ipike_payload_type_to_string(this_payload), this_payload); err = IPIKE_ISAKMP_UNSUPPORTED_PAYLOAD; } 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_PHASE_I_FAIL, ISAKMP_PACKET_ERROR, &ie->ike_sa->peer_addr, &ie->ike_sa->local_addr, 0, IP_NULL); return err; } return ipike_main_mode_update_state(ie); } /* *=========================================================================== * ipike_main_mode_add_reply_payloads *=========================================================================== */ IP_PUBLIC Ipike_error ipike_main_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; if ( ie->ike_sa->error != IPIKE_SUCCESS ) return ie->ike_sa->error; payload_ids = ipike_main_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_main_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_main_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; goto error; } 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); 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->local_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; 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_main_mode_cleartext_outgoing_message *=========================================================================== */ IP_PUBLIC Ipike_error ipike_main_mode_cleartext_outgoing_message( Ipike_isakmp_exchange* ie, Ipike_isakmp_header** outgoing_isakmp) { (void) ie; (void) outgoing_isakmp; return IPIKE_SUCCESS; } /* *=========================================================================== * ipike_main_mode_exchange_done *=========================================================================== */ IP_PUBLIC Ipike_error ipike_main_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, "Main 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 (main 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; } /* **************************************************************************** * END OF FILE **************************************************************************** */