+ switch (this->state)
+ {
+ case MM_INIT:
+ {
+
+ linked_list_t *list;
+ sa_payload_t *sa_payload;
+
+ this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ DBG0(DBG_IKE, "%H is initiating a Main Mode",
+ message->get_source(message));
+ this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
+
+ this->ike_sa->update_hosts(this->ike_sa,
+ message->get_destination(message),
+ message->get_source(message), TRUE);
+
+ sa_payload = (sa_payload_t*)message->get_payload(message,
+ SECURITY_ASSOCIATION_V1);
+ if (!sa_payload)
+ {
+ DBG1(DBG_IKE, "SA payload missing");
+ return FAILED;
+ }
+ list = sa_payload->get_proposals(sa_payload);
+ this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
+ list, FALSE);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ if (!this->proposal)
+ {
+ DBG1(DBG_IKE, "no proposal found");
+ return FAILED;
+ }
+ this->state = MM_SA;
+ return NEED_MORE;
+ }
+ case MM_SA:
+ {
+ ke_payload_t *ke_payload;
+ nonce_payload_t *nonce_payload;
+ u_int16_t group;
+
+ ke_payload = (ke_payload_t*)message->get_payload(message,
+ KEY_EXCHANGE_V1);
+ if (!ke_payload)
+ {
+ DBG1(DBG_IKE, "KE payload missing");
+ return FAILED;
+ }
+ this->dh_value = ke_payload->get_key_exchange_data(ke_payload);
+ this->dh_value = chunk_clone(this->dh_value);
+
+ if (!this->proposal->get_algorithm(this->proposal,
+ DIFFIE_HELLMAN_GROUP, &group, NULL))
+ {
+ DBG1(DBG_IKE, "DH group selection failed");
+ return FAILED;
+ }
+ this->dh = lib->crypto->create_dh(lib->crypto, group);
+ if (!this->dh)
+ {
+ DBG1(DBG_IKE, "negotiated DH group not supported");
+ return FAILED;
+ }
+ this->dh->set_other_public_value(this->dh, this->dh_value);
+
+
+ nonce_payload = (nonce_payload_t*)message->get_payload(message,
+ NONCE_V1);
+ if (!nonce_payload)
+ {
+ DBG1(DBG_IKE, "Nonce payload missing");
+ return FAILED;
+ }
+ this->nonce_i = nonce_payload->get_nonce(nonce_payload);
+
+ this->state = MM_KE;
+ return NEED_MORE;
+ }
+ case MM_KE:
+ {
+ enumerator_t *enumerator;
+ id_payload_t *id_payload;
+ identification_t *id, *any;
+
+ id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDii payload missing");
+ return FAILED;
+ }
+
+ id = id_payload->get_identification(id_payload);
+ any = identification_create_from_encoding(ID_ANY, chunk_empty);
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ any, id);
+ if (!enumerator->enumerate(enumerator, &this->peer_cfg))
+ {
+ DBG1(DBG_IKE, "no peer config found");
+ id->destroy(id);
+ any->destroy(any);
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ this->peer_cfg->get_ref(this->peer_cfg);
+ enumerator->destroy(enumerator);
+ any->destroy(any);
+
+ this->ike_sa->set_other_id(this->ike_sa, id);
+
+ this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
+
+ this->my_auth = get_auth_cfg(this, TRUE);
+ this->other_auth = get_auth_cfg(this, FALSE);
+ if (!this->my_auth || !this->other_auth)
+ {
+ DBG1(DBG_CFG, "auth config missing");
+ return FAILED;
+ }
+
+ /* TODO-IKEv1: authenticate peer */