/* * Abort the transaction, disconnecting it from state. * * Need to pass in serialno so that something sane can be logged when * the xauth request has already been deleted. Need to pass in * st_callback, but only when it needs to notify an abort. */ void xauth_pam_abort(struct state *st, bool call_callback) { struct xauth *xauth = st->st_xauth; if (xauth == NULL) { PEXPECT_LOG("XAUTH: #%lu: main-process: no thread to abort (already aborted?)", st->st_serialno); } else { st->st_xauth = NULL; pstats_xauth_aborted++; passert(!xauth->abort); passert(xauth->serialno == st->st_serialno); libreswan_log("XAUTH: #%lu: main-process: aborting authentication PAM-process for '%s'", st->st_serialno, xauth->ptarg.name); xauth->abort = true; /* * Don't hold back. * * XXX: need to fix child so that more friendly * SIGTERM is handled - currently the forked process * has it blocked by libvent. */ kill(xauth->child, SIGKILL); if (call_callback) { DBG(DBG_XAUTH, DBG_log("XAUTH: #%lu: main-process: notifying callback for user '%s'", st->st_serialno, xauth->ptarg.name)); xauth->callback(st, xauth->ptarg.name, false); } else { pfree_xauth(xauth); } } }
struct db_sa *oakley_alg_mergedb(struct alg_info_ike *ai, enum ikev1_auth_method auth_method, bool single_dh) { passert(ai != NULL); struct db_sa *gsp = NULL; /* Next two are for multiple proposals in aggressive mode... */ unsigned last_modp = 0; bool warned_dropped_dhgr = FALSE; int transcnt = 0; /* * for each group, we will create a new proposal item, and then * append it to the list of transforms in the conjoint point. * * when creating each item, we will use the first transform * from the base item as the template. */ FOR_EACH_IKE_INFO(ai, ike_info) { struct db_sa *emp_sp; passert(ike_info->ike_encrypt); passert(ike_info->ike_prf); passert(ike_info->ike_dh_group); unsigned ealg = ike_info->ike_encrypt->common.ikev1_oakley_id; unsigned halg = ike_info->ike_prf->common.ikev1_oakley_id; unsigned modp = ike_info->ike_dh_group->group; unsigned eklen = ike_info->ike_eklen; DBG(DBG_CONTROL, DBG_log("oakley_alg_makedb() processing ealg=%s=%u halg=%s=%u modp=%s=%u eklen=%u", ike_info->ike_encrypt->common.name, ealg, ike_info->ike_prf->common.name, halg, ike_info->ike_dh_group->common.name, modp, eklen)); const struct encrypt_desc *enc_desc = ike_info->ike_encrypt; if (eklen != 0 && !encrypt_has_key_bit_length(enc_desc, eklen)) { PEXPECT_LOG("IKEv1 proposal with ENCRYPT%s (specified) keylen:%d, not valid, should have been dropped", enc_desc->common.name, eklen); continue; } /* * copy the template */ emp_sp = sa_copy_sa(&oakley_empty); passert(emp_sp->dynamic); passert(emp_sp->prop_conj_cnt == 1); passert(emp_sp->prop_conjs[0].prop_cnt == 1); passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1); struct db_trans *trans = &emp_sp->prop_conjs[0].props[0].trans[0]; passert(trans->attr_cnt == 5); /* * See "struct db_attr otempty" above, and spdb.c, for * where these magic values come from. */ struct db_attr *enc = &trans->attrs[0]; struct db_attr *hash = &trans->attrs[1]; struct db_attr *auth = &trans->attrs[2]; struct db_attr *grp = &trans->attrs[3]; /* * auth type for IKE must be set. */ passert(auth->type.oakley == OAKLEY_AUTHENTICATION_METHOD); auth->val = auth_method; if (eklen > 0) { struct db_attr *enc_keylen = &trans->attrs[4]; passert(trans->attr_cnt == 5); passert(enc_keylen->type.oakley == OAKLEY_KEY_LENGTH); enc_keylen->val = eklen; } else { /* truncate */ trans->attr_cnt = 4; } passert(enc->type.oakley == OAKLEY_ENCRYPTION_ALGORITHM); if (ealg > 0) enc->val = ealg; /* * Either pass a hash algorithm or a PRF. * * Since AEAD algorithms don't need the hash, * but do need a PRF, the hash field can be * re-purposed as a PRF field. * * [cagney] While I suspect that type will * never initially be OAKLEY_PRF (it is * initialized using "struct db_attr otempty") * it doesn't hurt to be safe. */ passert(hash->type.oakley == OAKLEY_HASH_ALGORITHM || hash->type.oakley == OAKLEY_PRF); if (halg > 0) { hash->val = halg; if (ike_alg_enc_requires_integ(enc_desc)) { hash->type.oakley = OAKLEY_HASH_ALGORITHM; } else { hash->type.oakley = OAKLEY_PRF; } } passert(grp->type.oakley == OAKLEY_GROUP_DESCRIPTION); if (modp > 0) grp->val = modp; /* * Aggressive mode really only works with a single DH group. * If this is for Aggressive Mode, and we've previously seen * a different DH group, we try to deal with this. */ if (single_dh && transcnt > 0 && ike_info->ike_dh_group->group != last_modp) { if (last_modp == OAKLEY_GROUP_MODP1024 || last_modp == OAKLEY_GROUP_MODP1536) { /* * The previous group will work on old Cisco gear, * so we can discard this one. */ if (!warned_dropped_dhgr) { /* complain only once */ loglog(RC_LOG_SERIOUS, "multiple DH groups were set in aggressive mode. Only first one used."); } loglog(RC_LOG_SERIOUS, "transform (%s,%s,%s keylen %ld) ignored.", enum_name(&oakley_enc_names, ike_info->ike_encrypt->common.ikev1_oakley_id), enum_name(&oakley_hash_names, ike_info->ike_prf->common.ikev1_oakley_id), ike_info->ike_dh_group->common.name, (long)ike_info->ike_eklen); free_sa(&emp_sp); } else { /* * The previous group won't work on old Cisco gear, * so we discard the previous ones. * Of course this modp might be just as bad; * we won't look until the next one comes along. * * Lemma: there will be only a single previous * one in gsp (any others were discarded). */ loglog(RC_LOG_SERIOUS, "multiple DH groups in aggressive mode can cause interop failure"); loglog(RC_LOG_SERIOUS, "Deleting previous proposal in the hopes of selecting DH 2 or DH 5"); free_sa(&gsp); } warned_dropped_dhgr = TRUE; } if (emp_sp != NULL) { /* * Exclude 3des et.al. which do not include * default key lengths in the proposal. */ if (ike_info->ike_eklen == 0 && !ike_info->ike_encrypt->keylen_omitted) { const struct encrypt_desc *enc_desc = ike_info->ike_encrypt; int def_ks = enc_desc->keydeflen; passert(def_ks); /* ike=null not supported */ int max_ks = encrypt_max_key_bit_length(enc_desc); int ks; passert(emp_sp->dynamic); passert(emp_sp->prop_conj_cnt == 1); passert(emp_sp->prop_conjs[0].prop_cnt == 1); passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1); if (emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 4) { /* add a key length attribute of 0 */ struct db_trans *tr = &emp_sp->prop_conjs[0].props[0].trans[0]; const int n = tr->attr_cnt; /* 4, actually */ struct db_attr *old_attrs = tr->attrs; struct db_attr *new_attrs = alloc_bytes( (n + 1) * sizeof(old_attrs[0]), "extended trans"); passert(emp_sp->dynamic); passert(old_attrs[0].type.oakley != OAKLEY_KEY_LENGTH && old_attrs[1].type.oakley != OAKLEY_KEY_LENGTH && old_attrs[2].type.oakley != OAKLEY_KEY_LENGTH && old_attrs[3].type.oakley != OAKLEY_KEY_LENGTH); memcpy(new_attrs, old_attrs, n * sizeof(old_attrs[0])); new_attrs[n].type.oakley = OAKLEY_KEY_LENGTH; new_attrs[n].val = 0; pfree(old_attrs); tr->attrs = new_attrs; tr->attr_cnt++; } passert(emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 5); passert(emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].type.oakley == OAKLEY_KEY_LENGTH); /* * This odd FOR loop executes its body for * exactly two values of ks (max_ks and def_ks) * unless def_ks == max_ks, in which case it is * executed once. */ for (ks = max_ks; ; ks = def_ks) { emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].val = ks; if (gsp == NULL) { gsp = sa_copy_sa(emp_sp); } else { struct db_sa *new = sa_merge_proposals(gsp, emp_sp); free_sa(&gsp); gsp = new; } if (ks == def_ks) break; } free_sa(&emp_sp); } else { if (gsp != NULL) { /* now merge emp_sa and gsp */ struct db_sa *new = sa_merge_proposals(gsp, emp_sp); free_sa(&gsp); free_sa(&emp_sp); gsp = new; } else { gsp = emp_sp; emp_sp = NULL; } } last_modp = ike_info->ike_dh_group->group; }