static void aggr_outI1_continue(struct pluto_crypto_req_cont *pcrc , struct pluto_crypto_req *r , err_t ugh) { struct ke_continuation *ke = (struct ke_continuation *)pcrc; struct msg_digest *md = ke->md; struct state *const st = md->st; stf_status e; DBG(DBG_CONTROLMORE , DBG_log("aggr outI1: calculated ke+nonce, sending I1")); /* XXX should check out ugh */ passert(ugh == NULL); passert(cur_state == NULL); passert(st != NULL); passert(st->st_suspended_md == ke->md); st->st_suspended_md = NULL; /* no longer connected or suspended */ set_cur_state(st); st->st_calculating = FALSE; e = aggr_outI1_tail(pcrc, r); if(ke->md != NULL) { complete_state_transition(&ke->md, e); release_md(ke->md); } reset_globals(); passert(GLOBALS_ARE_RESET()); }
/* * delete all states that were created for a given connection, * additionally delete any states for which func(st, arg) * returns true. */ static void foreach_states_by_connection_func(struct connection *c , bool (*comparefunc)(struct state *st, struct connection *c, void *arg, int pass) , void (*successfunc)(struct state *st, struct connection *c, void *arg) , void *arg) { int pass; /* this kludge avoids an n^2 algorithm */ /* We take two passes so that we delete any ISAKMP SAs last. * This allows Delete Notifications to be sent. * ?? We could probably double the performance by caching any * ISAKMP SA states found in the first pass, avoiding a second. */ for (pass = 0; pass != 2; pass++) { int i; /* For each hash chain... */ for (i = 0; i < STATE_TABLE_SIZE; i++) { struct state *st; /* For each state in the hash chain... */ for (st = statetable[i]; st != NULL; ) { struct state *this = st; st = st->st_hashchain_next; /* before this is deleted */ /* on pass 2, ignore phase2 states */ if(pass == 1 && IS_ISAKMP_SA_ESTABLISHED(this->st_state)) { continue; } /* call comparison function */ if ((*comparefunc)(this, c, arg, pass)) { struct state *old_cur_state = cur_state == this? NULL : cur_state; #ifdef DEBUG lset_t old_cur_debugging = cur_debugging; #endif set_cur_state(this); (*successfunc)(this, c, arg); cur_state = old_cur_state; #ifdef DEBUG set_debugging(old_cur_debugging); #endif } } } } }
/* * continuation from second calculation (the DH one) * */ static void aggr_inI1_outR1_continue2(struct pluto_crypto_req_cont *pcrc, struct pluto_crypto_req *r, err_t ugh) { struct dh_continuation *dh = (struct dh_continuation *)pcrc; struct msg_digest *md = dh->dh_md; struct state *const st = md->st; stf_status e; DBG(DBG_CONTROL, DBG_log("aggr_inI1_outR1_continue2 for #%lu: calculated ke+nonce+DH, sending R1", dh->dh_pcrc.pcrc_serialno)); if (st == NULL) { loglog(RC_LOG_SERIOUS, "%s: Request was disconnected from state", __FUNCTION__); passert(dh->dh_pcrc.pcrc_serialno == SOS_NOBODY); /* transitional */ release_any_md(&dh->dh_md); return; } passert(dh->dh_pcrc.pcrc_serialno == st->st_serialno); /* transitional */ /* XXX should check out ugh */ passert(ugh == NULL); passert(cur_state == NULL); passert(st != NULL); passert(st->st_suspended_md == dh->dh_md); unset_suspended(st); /* no longer connected or suspended */ set_cur_state(st); DBG(DBG_CONTROLMORE, DBG_log("#%lu %s:%u st->st_calculating = FALSE;", st->st_serialno, __FUNCTION__, __LINE__)); st->st_calculating = FALSE; e = aggr_inI1_outR1_tail(pcrc, r); if (dh->dh_md != NULL) { complete_v1_state_transition(&dh->dh_md, e); release_any_md(&dh->dh_md); } reset_cur_state(); }
/* * for aggressive mode, this is sub-optimal, since we should have * had the crypto helper actually do everything, but we need to do * some additional work to set that all up, so this is fine for now. * */ static void aggr_inI1_outR1_continue1(struct pluto_crypto_req_cont *pcrc, struct pluto_crypto_req *r, err_t ugh) { struct ke_continuation *ke = (struct ke_continuation *)pcrc; struct msg_digest *md = ke->ke_md; struct state *const st = md->st; stf_status e; DBG(DBG_CONTROLMORE, DBG_log("aggr inI1_outR1: calculated ke+nonce, calculating DH")); if (st == NULL) { loglog(RC_LOG_SERIOUS, "%s: Request was disconnected from state", __FUNCTION__); release_any_md(&ke->ke_md); return; } /* XXX should check out ugh */ passert(ugh == NULL); passert(cur_state == NULL); passert(st != NULL); passert(st->st_suspended_md == ke->ke_md); unset_suspended(st); /* no longer connected or suspended */ set_cur_state(st); DBG(DBG_CONTROLMORE, DBG_log("#%lu %s:%u st->st_calculating = FALSE;", st->st_serialno, __FUNCTION__, __LINE__)); st->st_calculating = FALSE; /* unpack first calculation */ unpack_KE(st, r, &st->st_gr); /* unpack nonce too */ unpack_nonce(&st->st_nr, r); /* NOTE: the "r" reply will get freed by our caller */ /* set up second calculation */ { struct dh_continuation *dh = alloc_thing( struct dh_continuation, "aggr outR1 DH"); dh->dh_md = md; set_suspended(st, md); dh->dh_pcrc.pcrc_serialno = st->st_serialno; /* transitional */ pcrc_init(&dh->dh_pcrc, aggr_inI1_outR1_continue2); e = start_dh_secretiv(&dh->dh_pcrc, st, st->st_import, O_RESPONDER, st->st_oakley.group->group); if (e != STF_SUSPEND) { if (dh->dh_md != NULL) { complete_v1_state_transition(&dh->dh_md, e); release_any_md(&dh->dh_md); } } reset_cur_state(); } }