1*9ca241fcSyasuoka /* $OpenBSD: config.c,v 1.99 2024/09/15 11:08:50 yasuoka Exp $ */ 245ae9d61Sreyk 345ae9d61Sreyk /* 465c540d0Spatrick * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> 5fcebd35dSreyk * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> 645ae9d61Sreyk * 745ae9d61Sreyk * Permission to use, copy, modify, and distribute this software for any 845ae9d61Sreyk * purpose with or without fee is hereby granted, provided that the above 945ae9d61Sreyk * copyright notice and this permission notice appear in all copies. 1045ae9d61Sreyk * 1145ae9d61Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1245ae9d61Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1345ae9d61Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1445ae9d61Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1545ae9d61Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1645ae9d61Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1745ae9d61Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1845ae9d61Sreyk */ 1945ae9d61Sreyk 2045ae9d61Sreyk #include <sys/queue.h> 2145ae9d61Sreyk #include <sys/socket.h> 2245ae9d61Sreyk #include <sys/uio.h> 2345ae9d61Sreyk 2445ae9d61Sreyk #include <stdlib.h> 2545ae9d61Sreyk #include <stdio.h> 2645ae9d61Sreyk #include <unistd.h> 2745ae9d61Sreyk #include <string.h> 2845ae9d61Sreyk #include <signal.h> 2945ae9d61Sreyk #include <errno.h> 3045ae9d61Sreyk #include <err.h> 3145ae9d61Sreyk #include <event.h> 3245ae9d61Sreyk 33e8b444cdSreyk #include <openssl/evp.h> 34e8b444cdSreyk #include <openssl/pem.h> 35e8b444cdSreyk 3645ae9d61Sreyk #include "iked.h" 3745ae9d61Sreyk #include "ikev2.h" 3845ae9d61Sreyk 3945ae9d61Sreyk struct iked_sa * 4045ae9d61Sreyk config_new_sa(struct iked *env, int initiator) 4145ae9d61Sreyk { 4245ae9d61Sreyk struct iked_sa *sa; 4345ae9d61Sreyk 4445ae9d61Sreyk if ((sa = calloc(1, sizeof(*sa))) == NULL) 4545ae9d61Sreyk return (NULL); 4645ae9d61Sreyk 4745ae9d61Sreyk TAILQ_INIT(&sa->sa_proposals); 4845ae9d61Sreyk TAILQ_INIT(&sa->sa_childsas); 4945ae9d61Sreyk TAILQ_INIT(&sa->sa_flows); 50c45fd413Smikeb TAILQ_INIT(&sa->sa_requests); 51c45fd413Smikeb TAILQ_INIT(&sa->sa_responses); 5245ae9d61Sreyk sa->sa_hdr.sh_initiator = initiator; 53ae494144Sreyk sa->sa_type = IKED_SATYPE_LOCAL; 5445ae9d61Sreyk 5545ae9d61Sreyk if (initiator) 5645ae9d61Sreyk sa->sa_hdr.sh_ispi = config_getspi(); 5745ae9d61Sreyk else 5845ae9d61Sreyk sa->sa_hdr.sh_rspi = config_getspi(); 5945ae9d61Sreyk 6045ae9d61Sreyk gettimeofday(&sa->sa_timecreated, NULL); 6145ae9d61Sreyk memcpy(&sa->sa_timeused, &sa->sa_timecreated, sizeof(sa->sa_timeused)); 6245ae9d61Sreyk 63b41cc0c8Stobhe ikestat_inc(env, ikes_sa_created); 6445ae9d61Sreyk return (sa); 6545ae9d61Sreyk } 6645ae9d61Sreyk 67d09d3a7dSreyk uint64_t 6845ae9d61Sreyk config_getspi(void) 6945ae9d61Sreyk { 70d09d3a7dSreyk uint64_t spi; 7145ae9d61Sreyk 720868714eSderaadt do { 730868714eSderaadt arc4random_buf(&spi, sizeof spi); 740868714eSderaadt } while (spi == 0); 7545ae9d61Sreyk 7645ae9d61Sreyk return (spi); 7745ae9d61Sreyk } 7845ae9d61Sreyk 7945ae9d61Sreyk void 800cdab560Smarkus config_free_kex(struct iked_kex *kex) 810cdab560Smarkus { 820cdab560Smarkus if (kex == NULL) 830cdab560Smarkus return; 840cdab560Smarkus 85be2b38f5Sclaudio ibuf_free(kex->kex_inonce); 86be2b38f5Sclaudio ibuf_free(kex->kex_rnonce); 870cdab560Smarkus 880cdab560Smarkus group_free(kex->kex_dhgroup); 89be2b38f5Sclaudio ibuf_free(kex->kex_dhiexchange); 90be2b38f5Sclaudio ibuf_free(kex->kex_dhrexchange); 910cdab560Smarkus 920cdab560Smarkus free(kex); 930cdab560Smarkus } 940cdab560Smarkus 950cdab560Smarkus void 9665c540d0Spatrick config_free_fragments(struct iked_frag *frag) 9765c540d0Spatrick { 9865c540d0Spatrick size_t i; 9965c540d0Spatrick 10065c540d0Spatrick if (frag && frag->frag_arr) { 10165c540d0Spatrick for (i = 0; i < frag->frag_total; i++) { 10265c540d0Spatrick if (frag->frag_arr[i] != NULL) 10365c540d0Spatrick free(frag->frag_arr[i]->frag_data); 10465c540d0Spatrick free(frag->frag_arr[i]); 10565c540d0Spatrick } 10665c540d0Spatrick free(frag->frag_arr); 10765c540d0Spatrick bzero(frag, sizeof(struct iked_frag)); 10865c540d0Spatrick } 10965c540d0Spatrick } 11065c540d0Spatrick 11165c540d0Spatrick void 11245ae9d61Sreyk config_free_sa(struct iked *env, struct iked_sa *sa) 11345ae9d61Sreyk { 114055943a1Stobhe int i; 115055943a1Stobhe 116b3eeacebSmikeb timer_del(env, &sa->sa_timer); 117d52b1aceSpatrick timer_del(env, &sa->sa_keepalive); 1186e1880a3Smarkus timer_del(env, &sa->sa_rekey); 11981bdcbc1Smikeb 12065c540d0Spatrick config_free_fragments(&sa->sa_fragments); 12145ae9d61Sreyk config_free_proposals(&sa->sa_proposals, 0); 12245ae9d61Sreyk config_free_childsas(env, &sa->sa_childsas, NULL, NULL); 123264f8b22Stobhe sa_configure_iface(env, sa, 0); 1249dbd37b8Sreyk sa_free_flows(env, &sa->sa_flows); 12545ae9d61Sreyk 126f36db9c4Syasuoka iked_radius_acct_stop(env, sa); 127f36db9c4Syasuoka 12843be1c05Smarkus if (sa->sa_addrpool) { 12943be1c05Smarkus (void)RB_REMOVE(iked_addrpool, &env->sc_addrpool, sa); 13043be1c05Smarkus free(sa->sa_addrpool); 13143be1c05Smarkus } 13219dc8638Spatrick if (sa->sa_addrpool6) { 13319dc8638Spatrick (void)RB_REMOVE(iked_addrpool6, &env->sc_addrpool6, sa); 13419dc8638Spatrick free(sa->sa_addrpool6); 13519dc8638Spatrick } 13643be1c05Smarkus 137b3ef9220Sreyk if (sa->sa_policy) { 13832b6fc39Smarkus TAILQ_REMOVE(&sa->sa_policy->pol_sapeers, sa, sa_peer_entry); 13945ae9d61Sreyk policy_unref(env, sa->sa_policy); 140b3ef9220Sreyk } 14145ae9d61Sreyk 142c45fd413Smikeb ikev2_msg_flushqueue(env, &sa->sa_requests); 143c45fd413Smikeb ikev2_msg_flushqueue(env, &sa->sa_responses); 144c45fd413Smikeb 145be2b38f5Sclaudio ibuf_free(sa->sa_inonce); 146be2b38f5Sclaudio ibuf_free(sa->sa_rnonce); 14745ae9d61Sreyk 14845ae9d61Sreyk group_free(sa->sa_dhgroup); 149be2b38f5Sclaudio ibuf_free(sa->sa_dhiexchange); 150be2b38f5Sclaudio ibuf_free(sa->sa_dhrexchange); 15145ae9d61Sreyk 152be2b38f5Sclaudio ibuf_free(sa->sa_simult); 15383e6846fSmikeb 15445ae9d61Sreyk hash_free(sa->sa_prf); 15545ae9d61Sreyk hash_free(sa->sa_integr); 15645ae9d61Sreyk cipher_free(sa->sa_encr); 15745ae9d61Sreyk 158be2b38f5Sclaudio ibuf_free(sa->sa_key_d); 159be2b38f5Sclaudio ibuf_free(sa->sa_key_iauth); 160be2b38f5Sclaudio ibuf_free(sa->sa_key_rauth); 161be2b38f5Sclaudio ibuf_free(sa->sa_key_iencr); 162be2b38f5Sclaudio ibuf_free(sa->sa_key_rencr); 163be2b38f5Sclaudio ibuf_free(sa->sa_key_iprf); 164be2b38f5Sclaudio ibuf_free(sa->sa_key_rprf); 16545ae9d61Sreyk 166be2b38f5Sclaudio ibuf_free(sa->sa_1stmsg); 167be2b38f5Sclaudio ibuf_free(sa->sa_2ndmsg); 16845ae9d61Sreyk 169be2b38f5Sclaudio ibuf_free(sa->sa_iid.id_buf); 170be2b38f5Sclaudio ibuf_free(sa->sa_rid.id_buf); 171be2b38f5Sclaudio ibuf_free(sa->sa_icert.id_buf); 172be2b38f5Sclaudio ibuf_free(sa->sa_rcert.id_buf); 173055943a1Stobhe for (i = 0; i < IKED_SCERT_MAX; i++) 174be2b38f5Sclaudio ibuf_free(sa->sa_scert[i].id_buf); 175be2b38f5Sclaudio ibuf_free(sa->sa_localauth.id_buf); 176be2b38f5Sclaudio ibuf_free(sa->sa_peerauth.id_buf); 17745ae9d61Sreyk 178be2b38f5Sclaudio ibuf_free(sa->sa_eap.id_buf); 17945ae9d61Sreyk free(sa->sa_eapid); 180be2b38f5Sclaudio ibuf_free(sa->sa_eapmsk); 181*9ca241fcSyasuoka ibuf_free(sa->sa_eapclass); 18245ae9d61Sreyk 18352b3354cStobhe free(sa->sa_cp_addr); 18452b3354cStobhe free(sa->sa_cp_addr6); 1859ef39cf4Stobhe free(sa->sa_cp_dns); 18652b3354cStobhe 187160b250fSreyk free(sa->sa_tag); 188b41cc0c8Stobhe 189b41cc0c8Stobhe if (sa->sa_state == IKEV2_STATE_ESTABLISHED) 190b41cc0c8Stobhe ikestat_dec(env, ikes_sa_established_current); 191b41cc0c8Stobhe ikestat_inc(env, ikes_sa_removed); 192b41cc0c8Stobhe 193f36db9c4Syasuoka free(sa->sa_rad_addr); 194f36db9c4Syasuoka free(sa->sa_rad_addr6); 195f36db9c4Syasuoka iked_radius_request_free(env, sa->sa_radreq); 196f36db9c4Syasuoka 19745ae9d61Sreyk free(sa); 19845ae9d61Sreyk } 19945ae9d61Sreyk 20045ae9d61Sreyk struct iked_policy * 20145ae9d61Sreyk config_new_policy(struct iked *env) 20245ae9d61Sreyk { 20345ae9d61Sreyk struct iked_policy *pol; 20445ae9d61Sreyk 20545ae9d61Sreyk if ((pol = calloc(1, sizeof(*pol))) == NULL) 20645ae9d61Sreyk return (NULL); 20745ae9d61Sreyk 20832b6fc39Smarkus /* XXX caller does this again */ 20945ae9d61Sreyk TAILQ_INIT(&pol->pol_proposals); 21032b6fc39Smarkus TAILQ_INIT(&pol->pol_sapeers); 2111f864a9aStobhe TAILQ_INIT(&pol->pol_tssrc); 2121f864a9aStobhe TAILQ_INIT(&pol->pol_tsdst); 21332b6fc39Smarkus RB_INIT(&pol->pol_flows); 21445ae9d61Sreyk 21545ae9d61Sreyk return (pol); 21645ae9d61Sreyk } 21745ae9d61Sreyk 21845ae9d61Sreyk void 21945ae9d61Sreyk config_free_policy(struct iked *env, struct iked_policy *pol) 22045ae9d61Sreyk { 22145ae9d61Sreyk struct iked_sa *sa; 2221f864a9aStobhe struct iked_ts *tsi; 22345ae9d61Sreyk 22445ae9d61Sreyk if (pol->pol_flags & IKED_POLICY_REFCNT) 22545ae9d61Sreyk goto remove; 22645ae9d61Sreyk 227ac3a6947Stobhe /* 228ac3a6947Stobhe * Remove policy from the sc_policies list, but increment 229ac3a6947Stobhe * refcount for every SA linked for the policy. 230ac3a6947Stobhe */ 231ac3a6947Stobhe pol->pol_flags |= IKED_POLICY_REFCNT; 232ac3a6947Stobhe 233e2015428Sreyk TAILQ_REMOVE(&env->sc_policies, pol, pol_entry); 23445ae9d61Sreyk 23532b6fc39Smarkus TAILQ_FOREACH(sa, &pol->pol_sapeers, sa_peer_entry) { 23645ae9d61Sreyk if (sa->sa_policy == pol) 23745ae9d61Sreyk policy_ref(env, pol); 23832b6fc39Smarkus else 23932b6fc39Smarkus log_warnx("%s: ERROR: sa_policy %p != pol %p", 24032b6fc39Smarkus __func__, sa->sa_policy, pol); 24145ae9d61Sreyk } 24245ae9d61Sreyk 24345ae9d61Sreyk if (pol->pol_refcnt) 24445ae9d61Sreyk return; 24545ae9d61Sreyk 24645ae9d61Sreyk remove: 2471f864a9aStobhe while ((tsi = TAILQ_FIRST(&pol->pol_tssrc))) { 2481f864a9aStobhe TAILQ_REMOVE(&pol->pol_tssrc, tsi, ts_entry); 2491f864a9aStobhe free(tsi); 2501f864a9aStobhe } 2511f864a9aStobhe while ((tsi = TAILQ_FIRST(&pol->pol_tsdst))) { 2521f864a9aStobhe TAILQ_REMOVE(&pol->pol_tsdst, tsi, ts_entry); 2531f864a9aStobhe free(tsi); 2541f864a9aStobhe } 25545ae9d61Sreyk config_free_proposals(&pol->pol_proposals, 0); 256b0eeedd0Smikeb config_free_flows(env, &pol->pol_flows); 25745ae9d61Sreyk free(pol); 25845ae9d61Sreyk } 25945ae9d61Sreyk 26045ae9d61Sreyk struct iked_proposal * 261d09d3a7dSreyk config_add_proposal(struct iked_proposals *head, unsigned int id, 262d09d3a7dSreyk unsigned int proto) 26345ae9d61Sreyk { 26445ae9d61Sreyk struct iked_proposal *pp; 26545ae9d61Sreyk 26645ae9d61Sreyk TAILQ_FOREACH(pp, head, prop_entry) { 26745ae9d61Sreyk if (pp->prop_protoid == proto && 26845ae9d61Sreyk pp->prop_id == id) 26945ae9d61Sreyk return (pp); 27045ae9d61Sreyk } 27145ae9d61Sreyk 27245ae9d61Sreyk if ((pp = calloc(1, sizeof(*pp))) == NULL) 27345ae9d61Sreyk return (NULL); 27445ae9d61Sreyk 27545ae9d61Sreyk pp->prop_protoid = proto; 27645ae9d61Sreyk pp->prop_id = id; 27745ae9d61Sreyk 27845ae9d61Sreyk TAILQ_INSERT_TAIL(head, pp, prop_entry); 27945ae9d61Sreyk 28045ae9d61Sreyk return (pp); 28145ae9d61Sreyk } 28245ae9d61Sreyk 28345ae9d61Sreyk void 284822b336dStobhe config_free_proposal(struct iked_proposals *head, struct iked_proposal *prop) 285822b336dStobhe { 286822b336dStobhe TAILQ_REMOVE(head, prop, prop_entry); 287822b336dStobhe if (prop->prop_nxforms) 288822b336dStobhe free(prop->prop_xforms); 289822b336dStobhe free(prop); 290822b336dStobhe } 291822b336dStobhe 292822b336dStobhe void 293d09d3a7dSreyk config_free_proposals(struct iked_proposals *head, unsigned int proto) 29445ae9d61Sreyk { 2958177f5d5Stobhe struct iked_proposal *prop, *proptmp; 29645ae9d61Sreyk 2978177f5d5Stobhe TAILQ_FOREACH_SAFE(prop, head, prop_entry, proptmp) { 29845ae9d61Sreyk /* Free any proposal or only selected SA proto */ 29945ae9d61Sreyk if (proto != 0 && prop->prop_protoid != proto) 30045ae9d61Sreyk continue; 30145ae9d61Sreyk 30245ae9d61Sreyk log_debug("%s: free %p", __func__, prop); 30345ae9d61Sreyk 304822b336dStobhe config_free_proposal(head, prop); 30545ae9d61Sreyk } 30645ae9d61Sreyk } 30745ae9d61Sreyk 30845ae9d61Sreyk void 309b0eeedd0Smikeb config_free_flows(struct iked *env, struct iked_flows *head) 31045ae9d61Sreyk { 3119c3d68f7Stobhe struct iked_flow *flow; 31245ae9d61Sreyk 3139c3d68f7Stobhe while ((flow = RB_MIN(iked_flows, head))) { 31445ae9d61Sreyk log_debug("%s: free %p", __func__, flow); 3159dbd37b8Sreyk RB_REMOVE(iked_flows, head, flow); 31645ae9d61Sreyk flow_free(flow); 31745ae9d61Sreyk } 31845ae9d61Sreyk } 31945ae9d61Sreyk 32045ae9d61Sreyk void 32145ae9d61Sreyk config_free_childsas(struct iked *env, struct iked_childsas *head, 32245ae9d61Sreyk struct iked_spi *peerspi, struct iked_spi *localspi) 32345ae9d61Sreyk { 324fe856664Smbuhl struct iked_childsa *csa, *csatmp, *ipcomp; 32545ae9d61Sreyk 32645ae9d61Sreyk if (localspi != NULL) 32745ae9d61Sreyk bzero(localspi, sizeof(*localspi)); 32845ae9d61Sreyk 3298177f5d5Stobhe TAILQ_FOREACH_SAFE(csa, head, csa_entry, csatmp) { 33045ae9d61Sreyk if (peerspi != NULL) { 33145ae9d61Sreyk /* Only delete matching peer SPIs */ 33245ae9d61Sreyk if (peerspi->spi != csa->csa_peerspi) 33345ae9d61Sreyk continue; 33445ae9d61Sreyk 33545ae9d61Sreyk /* Store assigned local SPI */ 33645ae9d61Sreyk if (localspi != NULL && localspi->spi == 0) 33745ae9d61Sreyk memcpy(localspi, &csa->csa_spi, 33845ae9d61Sreyk sizeof(*localspi)); 33945ae9d61Sreyk } 34045ae9d61Sreyk log_debug("%s: free %p", __func__, csa); 34145ae9d61Sreyk 34245ae9d61Sreyk TAILQ_REMOVE(head, csa, csa_entry); 343b0eeedd0Smikeb if (csa->csa_loaded) { 344856dba1dSmikeb RB_REMOVE(iked_activesas, &env->sc_activesas, csa); 3458f6f6c19Stobhe (void)pfkey_sa_delete(env, csa); 346b0eeedd0Smikeb } 347fe856664Smbuhl if ((ipcomp = csa->csa_bundled) != NULL) { 348fe856664Smbuhl log_debug("%s: free IPCOMP %p", __func__, ipcomp); 349fe856664Smbuhl if (ipcomp->csa_loaded) 350fe856664Smbuhl (void)pfkey_sa_delete(env, ipcomp); 351fe856664Smbuhl childsa_free(ipcomp); 352e7fee6f8Stobhe } 35345ae9d61Sreyk childsa_free(csa); 354b41cc0c8Stobhe ikestat_inc(env, ikes_csa_removed); 35545ae9d61Sreyk } 35645ae9d61Sreyk } 35745ae9d61Sreyk 358822b336dStobhe int 359d09d3a7dSreyk config_add_transform(struct iked_proposal *prop, unsigned int type, 360d09d3a7dSreyk unsigned int id, unsigned int length, unsigned int keylength) 36145ae9d61Sreyk { 36245ae9d61Sreyk struct iked_transform *xform; 36345ae9d61Sreyk struct iked_constmap *map = NULL; 36445ae9d61Sreyk int score = 1; 365d09d3a7dSreyk unsigned int i; 36645ae9d61Sreyk 36745ae9d61Sreyk switch (type) { 36845ae9d61Sreyk case IKEV2_XFORMTYPE_ENCR: 36945ae9d61Sreyk map = ikev2_xformencr_map; 37045ae9d61Sreyk break; 37145ae9d61Sreyk case IKEV2_XFORMTYPE_PRF: 37245ae9d61Sreyk map = ikev2_xformprf_map; 37345ae9d61Sreyk break; 37445ae9d61Sreyk case IKEV2_XFORMTYPE_INTEGR: 37545ae9d61Sreyk map = ikev2_xformauth_map; 37645ae9d61Sreyk break; 37745ae9d61Sreyk case IKEV2_XFORMTYPE_DH: 37845ae9d61Sreyk map = ikev2_xformdh_map; 37945ae9d61Sreyk break; 38045ae9d61Sreyk case IKEV2_XFORMTYPE_ESN: 38145ae9d61Sreyk map = ikev2_xformesn_map; 38245ae9d61Sreyk break; 38345ae9d61Sreyk default: 38445ae9d61Sreyk log_debug("%s: invalid transform type %d", __func__, type); 385822b336dStobhe return (-2); 38645ae9d61Sreyk } 38745ae9d61Sreyk 38845ae9d61Sreyk for (i = 0; i < prop->prop_nxforms; i++) { 38945ae9d61Sreyk xform = prop->prop_xforms + i; 39045ae9d61Sreyk if (xform->xform_type == type && 39145ae9d61Sreyk xform->xform_id == id && 39245ae9d61Sreyk xform->xform_length == length) 393822b336dStobhe return (0); 39445ae9d61Sreyk } 39545ae9d61Sreyk 39645ae9d61Sreyk for (i = 0; i < prop->prop_nxforms; i++) { 39745ae9d61Sreyk xform = prop->prop_xforms + i; 39845ae9d61Sreyk if (xform->xform_type == type) { 39945ae9d61Sreyk switch (type) { 40045ae9d61Sreyk case IKEV2_XFORMTYPE_ENCR: 40145ae9d61Sreyk case IKEV2_XFORMTYPE_INTEGR: 40245ae9d61Sreyk score += 3; 40345ae9d61Sreyk break; 40445ae9d61Sreyk case IKEV2_XFORMTYPE_DH: 40545ae9d61Sreyk score += 2; 40645ae9d61Sreyk break; 40745ae9d61Sreyk default: 40845ae9d61Sreyk score += 1; 40945ae9d61Sreyk break; 41045ae9d61Sreyk } 41145ae9d61Sreyk } 41245ae9d61Sreyk } 41345ae9d61Sreyk 41498a76b0dSderaadt if ((xform = reallocarray(prop->prop_xforms, 41598a76b0dSderaadt prop->prop_nxforms + 1, sizeof(*xform))) == NULL) { 416822b336dStobhe return (-1); 41745ae9d61Sreyk } 41845ae9d61Sreyk 41945ae9d61Sreyk prop->prop_xforms = xform; 42045ae9d61Sreyk xform = prop->prop_xforms + prop->prop_nxforms++; 42145ae9d61Sreyk bzero(xform, sizeof(*xform)); 42245ae9d61Sreyk 42345ae9d61Sreyk xform->xform_type = type; 42445ae9d61Sreyk xform->xform_id = id; 42545ae9d61Sreyk xform->xform_length = length; 42645ae9d61Sreyk xform->xform_keylength = keylength; 42745ae9d61Sreyk xform->xform_score = score; 42845ae9d61Sreyk xform->xform_map = map; 42945ae9d61Sreyk 430822b336dStobhe return (0); 43145ae9d61Sreyk } 43245ae9d61Sreyk 43345ae9d61Sreyk struct iked_transform * 434975f0a0eStobhe config_findtransform_ext(struct iked_proposals *props, uint8_t type, int id, 435d09d3a7dSreyk unsigned int proto) 43645ae9d61Sreyk { 43745ae9d61Sreyk struct iked_proposal *prop; 43845ae9d61Sreyk struct iked_transform *xform; 439d09d3a7dSreyk unsigned int i; 44045ae9d61Sreyk 44145ae9d61Sreyk /* Search of the first transform with the desired type */ 44245ae9d61Sreyk TAILQ_FOREACH(prop, props, prop_entry) { 4439be30034Smarkus /* Find any proposal or only selected SA proto */ 4449be30034Smarkus if (proto != 0 && prop->prop_protoid != proto) 4459be30034Smarkus continue; 44645ae9d61Sreyk for (i = 0; i < prop->prop_nxforms; i++) { 44745ae9d61Sreyk xform = prop->prop_xforms + i; 448975f0a0eStobhe /* optional lookup of specific transform */ 449975f0a0eStobhe if (id >= 0 && xform->xform_id != id) 450975f0a0eStobhe continue; 45145ae9d61Sreyk if (xform->xform_type == type) 45245ae9d61Sreyk return (xform); 45345ae9d61Sreyk } 45445ae9d61Sreyk } 45545ae9d61Sreyk 45645ae9d61Sreyk return (NULL); 45745ae9d61Sreyk } 45845ae9d61Sreyk 459975f0a0eStobhe struct iked_transform * 460975f0a0eStobhe config_findtransform(struct iked_proposals *props, uint8_t type, 461975f0a0eStobhe unsigned int proto) 462975f0a0eStobhe { 463975f0a0eStobhe return config_findtransform_ext(props, type, -1, proto); 464975f0a0eStobhe } 465975f0a0eStobhe 46645ae9d61Sreyk struct iked_user * 46745ae9d61Sreyk config_new_user(struct iked *env, struct iked_user *new) 46845ae9d61Sreyk { 46945ae9d61Sreyk struct iked_user *usr, *old; 47045ae9d61Sreyk 47145ae9d61Sreyk if ((usr = calloc(1, sizeof(*usr))) == NULL) 47245ae9d61Sreyk return (NULL); 47345ae9d61Sreyk 47445ae9d61Sreyk memcpy(usr, new, sizeof(*usr)); 47545ae9d61Sreyk 47645ae9d61Sreyk if ((old = RB_INSERT(iked_users, &env->sc_users, usr)) != NULL) { 47745ae9d61Sreyk /* Update the password of an existing user*/ 478c2defdfcStobhe memcpy(old->usr_pass, new->usr_pass, IKED_PASSWORD_SIZE); 47945ae9d61Sreyk 48045ae9d61Sreyk log_debug("%s: updating user %s", __func__, usr->usr_name); 4816c3f70ddSderaadt freezero(usr, sizeof *usr); 48245ae9d61Sreyk 48345ae9d61Sreyk return (old); 48445ae9d61Sreyk } 48545ae9d61Sreyk 48645ae9d61Sreyk log_debug("%s: inserting new user %s", __func__, usr->usr_name); 48745ae9d61Sreyk return (usr); 48845ae9d61Sreyk } 48945ae9d61Sreyk 49045ae9d61Sreyk /* 49145ae9d61Sreyk * Inter-process communication of configuration items. 49245ae9d61Sreyk */ 49345ae9d61Sreyk 49445ae9d61Sreyk int 495d09d3a7dSreyk config_setcoupled(struct iked *env, unsigned int couple) 496fc20f985Sreyk { 497d09d3a7dSreyk unsigned int type; 498fc20f985Sreyk 499fc20f985Sreyk type = couple ? IMSG_CTL_COUPLE : IMSG_CTL_DECOUPLE; 500c205e972Sreyk proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0); 501fc20f985Sreyk 502fc20f985Sreyk return (0); 503fc20f985Sreyk } 504fc20f985Sreyk 505fc20f985Sreyk int 506d09d3a7dSreyk config_getcoupled(struct iked *env, unsigned int type) 507fc20f985Sreyk { 5088f6f6c19Stobhe return (pfkey_couple(env, &env->sc_sas, 509fc20f985Sreyk type == IMSG_CTL_COUPLE ? 1 : 0)); 510fc20f985Sreyk } 511fc20f985Sreyk 512fc20f985Sreyk int 513d09d3a7dSreyk config_setmode(struct iked *env, unsigned int passive) 514fc20f985Sreyk { 515d09d3a7dSreyk unsigned int type; 516fc20f985Sreyk 5173fdfc9aaStobhe /* 5183fdfc9aaStobhe * In order to control the startup of the processes, 5193fdfc9aaStobhe * the messages are sent in this order: 5203fdfc9aaStobhe * PROC_PARENT -> PROC_CERT -> PROC_PARENT -> PROC_IKEV2 5213fdfc9aaStobhe * so PROC_CERT is ready before PROC_IKEV2 is activated. 5223fdfc9aaStobhe */ 523fc20f985Sreyk type = passive ? IMSG_CTL_PASSIVE : IMSG_CTL_ACTIVE; 5243fdfc9aaStobhe proc_compose(&env->sc_ps, PROC_CERT, type, NULL, 0); 525fc20f985Sreyk 526fc20f985Sreyk return (0); 527fc20f985Sreyk } 528fc20f985Sreyk 529fc20f985Sreyk int 530d09d3a7dSreyk config_getmode(struct iked *env, unsigned int type) 531fc20f985Sreyk { 532d09d3a7dSreyk uint8_t old; 533d09d3a7dSreyk unsigned char *mode[] = { "active", "passive" }; 534fc20f985Sreyk 535fc20f985Sreyk old = env->sc_passive ? 1 : 0; 536fc20f985Sreyk env->sc_passive = type == IMSG_CTL_PASSIVE ? 1 : 0; 537fc20f985Sreyk 538fc20f985Sreyk if (old == env->sc_passive) 539fc20f985Sreyk return (0); 540fc20f985Sreyk 541fc20f985Sreyk log_debug("%s: mode %s -> %s", __func__, 542fc20f985Sreyk mode[old], mode[env->sc_passive]); 543fc20f985Sreyk 544fc20f985Sreyk return (0); 545fc20f985Sreyk } 546fc20f985Sreyk 547fc20f985Sreyk int 548d09d3a7dSreyk config_setreset(struct iked *env, unsigned int mode, enum privsep_procid id) 54945ae9d61Sreyk { 550c205e972Sreyk proc_compose(&env->sc_ps, id, IMSG_CTL_RESET, &mode, sizeof(mode)); 55145ae9d61Sreyk return (0); 55245ae9d61Sreyk } 55345ae9d61Sreyk 55445ae9d61Sreyk int 55545ae9d61Sreyk config_getreset(struct iked *env, struct imsg *imsg) 55645ae9d61Sreyk { 557d09d3a7dSreyk unsigned int mode; 55845ae9d61Sreyk 55945ae9d61Sreyk IMSG_SIZE_CHECK(imsg, &mode); 56045ae9d61Sreyk memcpy(&mode, imsg->data, sizeof(mode)); 56145ae9d61Sreyk 56291e971e4Stobhe return (config_doreset(env, mode)); 56391e971e4Stobhe } 56491e971e4Stobhe 56591e971e4Stobhe int 56691e971e4Stobhe config_doreset(struct iked *env, unsigned int mode) 56791e971e4Stobhe { 56891e971e4Stobhe struct iked_policy *pol, *poltmp; 56991e971e4Stobhe struct iked_sa *sa; 57091e971e4Stobhe struct iked_user *usr; 57191e971e4Stobhe 57291e971e4Stobhe if (mode == RESET_ALL || mode == RESET_POLICY) { 57345ae9d61Sreyk log_debug("%s: flushing policies", __func__); 5748177f5d5Stobhe TAILQ_FOREACH_SAFE(pol, &env->sc_policies, pol_entry, poltmp) { 57545ae9d61Sreyk config_free_policy(env, pol); 57645ae9d61Sreyk } 57745ae9d61Sreyk } 57845ae9d61Sreyk 57991e971e4Stobhe if (mode == RESET_ALL || mode == RESET_SA) { 58045ae9d61Sreyk log_debug("%s: flushing SAs", __func__); 5819c3d68f7Stobhe while ((sa = RB_MIN(iked_sas, &env->sc_sas))) { 582ea5b9487Stobhe /* for RESET_SA we try send a DELETE */ 583ea5b9487Stobhe if (mode == RESET_ALL || 584ea5b9487Stobhe ikev2_ike_sa_delete(env, sa) != 0) { 5854697d2e3Smarkus RB_REMOVE(iked_sas, &env->sc_sas, sa); 586ea67155dStobhe if (sa->sa_dstid_entry_valid) 587ea67155dStobhe sa_dstid_remove(env, sa); 58845ae9d61Sreyk config_free_sa(env, sa); 58945ae9d61Sreyk } 59045ae9d61Sreyk } 591ea5b9487Stobhe } 59245ae9d61Sreyk 59391e971e4Stobhe if (mode == RESET_ALL || mode == RESET_USER) { 59445ae9d61Sreyk log_debug("%s: flushing users", __func__); 5959c3d68f7Stobhe while ((usr = RB_MIN(iked_users, &env->sc_users))) { 59645ae9d61Sreyk RB_REMOVE(iked_users, &env->sc_users, usr); 59745ae9d61Sreyk free(usr); 59845ae9d61Sreyk } 59945ae9d61Sreyk } 60045ae9d61Sreyk 601f36db9c4Syasuoka if (mode == RESET_ALL || mode == RESET_RADIUS) { 602f36db9c4Syasuoka struct iked_radserver_req *req; 603f36db9c4Syasuoka struct iked_radserver *rad, *radt; 604f36db9c4Syasuoka struct iked_radcfgmap *cfg, *cfgt; 605f36db9c4Syasuoka struct iked_raddae *dae, *daet; 606f36db9c4Syasuoka struct iked_radclient *client, *clientt; 607f36db9c4Syasuoka 608f36db9c4Syasuoka TAILQ_FOREACH_SAFE(rad, &env->sc_radauthservers, rs_entry, 609f36db9c4Syasuoka radt) { 610f36db9c4Syasuoka close(rad->rs_sock); 611f36db9c4Syasuoka event_del(&rad->rs_ev); 612f36db9c4Syasuoka TAILQ_REMOVE(&env->sc_radauthservers, rad, rs_entry); 613f36db9c4Syasuoka while ((req = TAILQ_FIRST(&rad->rs_reqs)) != NULL) 614f36db9c4Syasuoka iked_radius_request_free(env, req); 615f36db9c4Syasuoka freezero(rad, sizeof(*rad)); 616f36db9c4Syasuoka } 617f36db9c4Syasuoka TAILQ_FOREACH_SAFE(rad, &env->sc_radacctservers, rs_entry, 618f36db9c4Syasuoka radt) { 619f36db9c4Syasuoka close(rad->rs_sock); 620f36db9c4Syasuoka event_del(&rad->rs_ev); 621f36db9c4Syasuoka TAILQ_REMOVE(&env->sc_radacctservers, rad, rs_entry); 622f36db9c4Syasuoka while ((req = TAILQ_FIRST(&rad->rs_reqs)) != NULL) 623f36db9c4Syasuoka iked_radius_request_free(env, req); 624f36db9c4Syasuoka freezero(rad, sizeof(*rad)); 625f36db9c4Syasuoka } 626f36db9c4Syasuoka TAILQ_FOREACH_SAFE(cfg, &env->sc_radcfgmaps, entry, cfgt) { 627f36db9c4Syasuoka TAILQ_REMOVE(&env->sc_radcfgmaps, cfg, entry); 628f36db9c4Syasuoka free(cfg); 629f36db9c4Syasuoka } 630f36db9c4Syasuoka TAILQ_FOREACH_SAFE(dae, &env->sc_raddaes, rd_entry, daet) { 631f36db9c4Syasuoka close(dae->rd_sock); 632f36db9c4Syasuoka event_del(&dae->rd_ev); 633f36db9c4Syasuoka TAILQ_REMOVE(&env->sc_raddaes, dae, rd_entry); 634f36db9c4Syasuoka free(dae); 635f36db9c4Syasuoka } 636f36db9c4Syasuoka TAILQ_FOREACH_SAFE(client, &env->sc_raddaeclients, rc_entry, 637f36db9c4Syasuoka clientt) { 638f36db9c4Syasuoka TAILQ_REMOVE(&env->sc_raddaeclients, client, rc_entry); 639f36db9c4Syasuoka free(client); 640f36db9c4Syasuoka } 641f36db9c4Syasuoka } 642f36db9c4Syasuoka 64345ae9d61Sreyk return (0); 64445ae9d61Sreyk } 64545ae9d61Sreyk 6461ae9ce49Stobhe /* 6471ae9ce49Stobhe * The first call of this function sets the UDP socket for IKEv2. 6481ae9ce49Stobhe * The second call is optional, setting the UDP socket used for NAT-T. 6491ae9ce49Stobhe */ 65045ae9d61Sreyk int 65145ae9d61Sreyk config_setsocket(struct iked *env, struct sockaddr_storage *ss, 652f2f2a684Sreyk in_port_t port, enum privsep_procid id) 65345ae9d61Sreyk { 65445ae9d61Sreyk int s; 65545ae9d61Sreyk 65645ae9d61Sreyk if ((s = udp_bind((struct sockaddr *)ss, port)) == -1) 65745ae9d61Sreyk return (-1); 658bf556abcSreyk proc_compose_imsg(&env->sc_ps, id, -1, 659c205e972Sreyk IMSG_UDP_SOCKET, -1, s, ss, sizeof(*ss)); 66045ae9d61Sreyk return (0); 66145ae9d61Sreyk } 66245ae9d61Sreyk 66345ae9d61Sreyk int 66445ae9d61Sreyk config_getsocket(struct iked *env, struct imsg *imsg, 66545ae9d61Sreyk void (*cb)(int, short, void *)) 66645ae9d61Sreyk { 6676acea849Stobhe struct iked_socket *sock, **sock0 = NULL, **sock1 = NULL; 66845ae9d61Sreyk 66945ae9d61Sreyk if ((sock = calloc(1, sizeof(*sock))) == NULL) 67045ae9d61Sreyk fatal("config_getsocket: calloc"); 67145ae9d61Sreyk 67245ae9d61Sreyk IMSG_SIZE_CHECK(imsg, &sock->sock_addr); 67345ae9d61Sreyk 67445ae9d61Sreyk memcpy(&sock->sock_addr, imsg->data, sizeof(sock->sock_addr)); 675fecd42b7Sclaudio sock->sock_fd = imsg_get_fd(imsg); 67645ae9d61Sreyk sock->sock_env = env; 67745ae9d61Sreyk 678fecd42b7Sclaudio log_debug("%s: received socket fd %d", __func__, sock->sock_fd); 679fecd42b7Sclaudio 680ae494144Sreyk switch (sock->sock_addr.ss_family) { 681ae494144Sreyk case AF_INET: 6821ae9ce49Stobhe sock0 = &env->sc_sock4[0]; 6831ae9ce49Stobhe sock1 = &env->sc_sock4[1]; 684ae494144Sreyk break; 685ae494144Sreyk case AF_INET6: 6861ae9ce49Stobhe sock0 = &env->sc_sock6[0]; 6871ae9ce49Stobhe sock1 = &env->sc_sock6[1]; 688ae494144Sreyk break; 689ae494144Sreyk default: 6901ae9ce49Stobhe fatal("config_getsocket: socket af: %u", 6911ae9ce49Stobhe sock->sock_addr.ss_family); 692ae494144Sreyk /* NOTREACHED */ 693ae494144Sreyk } 6941ae9ce49Stobhe if (*sock0 == NULL) 6951ae9ce49Stobhe *sock0 = sock; 6961ae9ce49Stobhe else if (*sock1 == NULL) 6971ae9ce49Stobhe *sock1 = sock; 6981ae9ce49Stobhe else 6991ae9ce49Stobhe fatalx("%s: too many call", __func__); 700ae494144Sreyk 70145ae9d61Sreyk event_set(&sock->sock_ev, sock->sock_fd, 70245ae9d61Sreyk EV_READ|EV_PERSIST, cb, sock); 70345ae9d61Sreyk 70445ae9d61Sreyk return (0); 70545ae9d61Sreyk } 70645ae9d61Sreyk 707ac16f2e6Stobhe void 708ac16f2e6Stobhe config_enablesocket(struct iked *env) 709ac16f2e6Stobhe { 710ac16f2e6Stobhe struct iked_socket *sock; 711ac16f2e6Stobhe size_t i; 712ac16f2e6Stobhe 713ac16f2e6Stobhe for (i = 0; i < nitems(env->sc_sock4); i++) 714ac16f2e6Stobhe if ((sock = env->sc_sock4[i]) != NULL) 715ac16f2e6Stobhe event_add(&sock->sock_ev, NULL); 716ac16f2e6Stobhe for (i = 0; i < nitems(env->sc_sock6); i++) 717ac16f2e6Stobhe if ((sock = env->sc_sock6[i]) != NULL) 718ac16f2e6Stobhe event_add(&sock->sock_ev, NULL); 719ac16f2e6Stobhe } 720ac16f2e6Stobhe 72145ae9d61Sreyk int 722ba38eea7Stobhe config_setpfkey(struct iked *env) 72345ae9d61Sreyk { 72445ae9d61Sreyk int s; 72545ae9d61Sreyk 7268f6f6c19Stobhe if ((s = pfkey_socket(env)) == -1) 72745ae9d61Sreyk return (-1); 728ba38eea7Stobhe proc_compose_imsg(&env->sc_ps, PROC_IKEV2, -1, 729c205e972Sreyk IMSG_PFKEY_SOCKET, -1, s, NULL, 0); 73045ae9d61Sreyk return (0); 73145ae9d61Sreyk } 73245ae9d61Sreyk 73345ae9d61Sreyk int 7346417b90fSreyk config_getpfkey(struct iked *env, struct imsg *imsg) 73545ae9d61Sreyk { 736fecd42b7Sclaudio int fd = imsg_get_fd(imsg); 737fecd42b7Sclaudio 738fecd42b7Sclaudio log_debug("%s: received pfkey fd %d", __func__, fd); 739fecd42b7Sclaudio pfkey_init(env, fd); 74045ae9d61Sreyk return (0); 74145ae9d61Sreyk } 74245ae9d61Sreyk 74345ae9d61Sreyk int 744f2f2a684Sreyk config_setuser(struct iked *env, struct iked_user *usr, enum privsep_procid id) 74545ae9d61Sreyk { 74645ae9d61Sreyk if (env->sc_opts & IKED_OPT_NOACTION) { 74745ae9d61Sreyk print_user(usr); 74845ae9d61Sreyk return (0); 74945ae9d61Sreyk } 75045ae9d61Sreyk 751c205e972Sreyk proc_compose(&env->sc_ps, id, IMSG_CFG_USER, usr, sizeof(*usr)); 75245ae9d61Sreyk return (0); 75345ae9d61Sreyk } 75445ae9d61Sreyk 75545ae9d61Sreyk int 75645ae9d61Sreyk config_getuser(struct iked *env, struct imsg *imsg) 75745ae9d61Sreyk { 75845ae9d61Sreyk struct iked_user usr; 7599b3346f9Stobhe int ret = -1; 76045ae9d61Sreyk 76145ae9d61Sreyk IMSG_SIZE_CHECK(imsg, &usr); 76245ae9d61Sreyk memcpy(&usr, imsg->data, sizeof(usr)); 76345ae9d61Sreyk 7649b3346f9Stobhe if (config_new_user(env, &usr) != NULL) { 76545ae9d61Sreyk print_user(&usr); 7669b3346f9Stobhe ret = 0; 7679b3346f9Stobhe } 76845ae9d61Sreyk 7699b3346f9Stobhe explicit_bzero(&usr, sizeof(usr)); 7709b3346f9Stobhe return (ret); 77145ae9d61Sreyk } 77245ae9d61Sreyk 77345ae9d61Sreyk int 77445ae9d61Sreyk config_setpolicy(struct iked *env, struct iked_policy *pol, 775f2f2a684Sreyk enum privsep_procid id) 77645ae9d61Sreyk { 77745ae9d61Sreyk struct iked_proposal *prop; 77845ae9d61Sreyk struct iked_transform *xform; 779fb5e93d4Smikeb size_t iovcnt, j, c = 0; 78045ae9d61Sreyk struct iovec iov[IOV_MAX]; 78145ae9d61Sreyk 78245ae9d61Sreyk iovcnt = 1; 78345ae9d61Sreyk TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) { 78445ae9d61Sreyk iovcnt += prop->prop_nxforms + 1; 78545ae9d61Sreyk } 78645ae9d61Sreyk 78745ae9d61Sreyk if (iovcnt > IOV_MAX) { 788fb5e93d4Smikeb log_warn("%s: too many proposals", __func__); 78945ae9d61Sreyk return (-1); 79045ae9d61Sreyk } 79145ae9d61Sreyk 79245ae9d61Sreyk iov[c].iov_base = pol; 79345ae9d61Sreyk iov[c++].iov_len = sizeof(*pol); 79445ae9d61Sreyk 79545ae9d61Sreyk TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) { 79645ae9d61Sreyk iov[c].iov_base = prop; 79745ae9d61Sreyk iov[c++].iov_len = sizeof(*prop); 79845ae9d61Sreyk 79945ae9d61Sreyk for (j = 0; j < prop->prop_nxforms; j++) { 80045ae9d61Sreyk xform = prop->prop_xforms + j; 80145ae9d61Sreyk 80245ae9d61Sreyk iov[c].iov_base = xform; 80345ae9d61Sreyk iov[c++].iov_len = sizeof(*xform); 80445ae9d61Sreyk } 80545ae9d61Sreyk } 80645ae9d61Sreyk 80745ae9d61Sreyk print_policy(pol); 808e54c4fa7Sreyk 809e54c4fa7Sreyk if (env->sc_opts & IKED_OPT_NOACTION) 81045ae9d61Sreyk return (0); 81145ae9d61Sreyk 812fb5e93d4Smikeb if (proc_composev(&env->sc_ps, id, IMSG_CFG_POLICY, iov, 813fb5e93d4Smikeb iovcnt) == -1) { 814fb5e93d4Smikeb log_debug("%s: proc_composev failed", __func__); 81545ae9d61Sreyk return (-1); 816fb5e93d4Smikeb } 817fb5e93d4Smikeb 818fb5e93d4Smikeb return (0); 819fb5e93d4Smikeb } 820fb5e93d4Smikeb 821fb5e93d4Smikeb int 822fb5e93d4Smikeb config_setflow(struct iked *env, struct iked_policy *pol, 823fb5e93d4Smikeb enum privsep_procid id) 824fb5e93d4Smikeb { 825fb5e93d4Smikeb struct iked_flow *flow; 826fb5e93d4Smikeb struct iovec iov[2]; 827fb5e93d4Smikeb 828fb5e93d4Smikeb if (env->sc_opts & IKED_OPT_NOACTION) 829fb5e93d4Smikeb return (0); 830fb5e93d4Smikeb 831fb5e93d4Smikeb RB_FOREACH(flow, iked_flows, &pol->pol_flows) { 832fb5e93d4Smikeb iov[0].iov_base = &pol->pol_id; 833fb5e93d4Smikeb iov[0].iov_len = sizeof(pol->pol_id); 834fb5e93d4Smikeb iov[1].iov_base = flow; 835fb5e93d4Smikeb iov[1].iov_len = sizeof(*flow); 836fb5e93d4Smikeb 837fb5e93d4Smikeb if (proc_composev(&env->sc_ps, id, IMSG_CFG_FLOW, 838fb5e93d4Smikeb iov, 2) == -1) { 839fb5e93d4Smikeb log_debug("%s: proc_composev failed", __func__); 840fb5e93d4Smikeb return (-1); 841fb5e93d4Smikeb } 842fb5e93d4Smikeb } 84345ae9d61Sreyk 84445ae9d61Sreyk return (0); 84545ae9d61Sreyk } 84645ae9d61Sreyk 84745ae9d61Sreyk int 84845ae9d61Sreyk config_getpolicy(struct iked *env, struct imsg *imsg) 84945ae9d61Sreyk { 850e2015428Sreyk struct iked_policy *pol; 85145ae9d61Sreyk struct iked_proposal pp, *prop; 85253d22e8fStobhe struct iked_transform xf; 85345ae9d61Sreyk off_t offset = 0; 854d09d3a7dSreyk unsigned int i, j; 855d09d3a7dSreyk uint8_t *buf = (uint8_t *)imsg->data; 85645ae9d61Sreyk 85745ae9d61Sreyk IMSG_SIZE_CHECK(imsg, pol); 85845ae9d61Sreyk log_debug("%s: received policy", __func__); 85945ae9d61Sreyk 86045ae9d61Sreyk if ((pol = config_new_policy(NULL)) == NULL) 86145ae9d61Sreyk fatal("config_getpolicy: new policy"); 86245ae9d61Sreyk 86345ae9d61Sreyk memcpy(pol, buf, sizeof(*pol)); 86445ae9d61Sreyk offset += sizeof(*pol); 86545ae9d61Sreyk 8661f864a9aStobhe TAILQ_INIT(&pol->pol_tssrc); 8671f864a9aStobhe TAILQ_INIT(&pol->pol_tsdst); 86845ae9d61Sreyk TAILQ_INIT(&pol->pol_proposals); 86932b6fc39Smarkus TAILQ_INIT(&pol->pol_sapeers); 8709dbd37b8Sreyk RB_INIT(&pol->pol_flows); 87145ae9d61Sreyk 87245ae9d61Sreyk for (i = 0; i < pol->pol_nproposals; i++) { 87345ae9d61Sreyk memcpy(&pp, buf + offset, sizeof(pp)); 87445ae9d61Sreyk offset += sizeof(pp); 87545ae9d61Sreyk 87645ae9d61Sreyk if ((prop = config_add_proposal(&pol->pol_proposals, 87745ae9d61Sreyk pp.prop_id, pp.prop_protoid)) == NULL) 87845ae9d61Sreyk fatal("config_getpolicy: add proposal"); 87945ae9d61Sreyk 88045ae9d61Sreyk for (j = 0; j < pp.prop_nxforms; j++) { 88145ae9d61Sreyk memcpy(&xf, buf + offset, sizeof(xf)); 88245ae9d61Sreyk offset += sizeof(xf); 88345ae9d61Sreyk 88453d22e8fStobhe if (config_add_transform(prop, xf.xform_type, 88545ae9d61Sreyk xf.xform_id, xf.xform_length, 886822b336dStobhe xf.xform_keylength) != 0) 88745ae9d61Sreyk fatal("config_getpolicy: add transform"); 88845ae9d61Sreyk } 88945ae9d61Sreyk } 89045ae9d61Sreyk 891fb5e93d4Smikeb /* Flows are sent separately */ 892fb5e93d4Smikeb pol->pol_nflows = 0; 89345ae9d61Sreyk 894e2015428Sreyk TAILQ_INSERT_TAIL(&env->sc_policies, pol, pol_entry); 89545ae9d61Sreyk 896e2015428Sreyk if (pol->pol_flags & IKED_POLICY_DEFAULT) { 897e2015428Sreyk /* Only one default policy, just free/unref the old one */ 898e2015428Sreyk if (env->sc_defaultcon != NULL) 899e2015428Sreyk config_free_policy(env, env->sc_defaultcon); 90045ae9d61Sreyk env->sc_defaultcon = pol; 901e2015428Sreyk } 90245ae9d61Sreyk 90345ae9d61Sreyk return (0); 90445ae9d61Sreyk } 905e2015428Sreyk 906e2015428Sreyk int 907fb5e93d4Smikeb config_getflow(struct iked *env, struct imsg *imsg) 908fb5e93d4Smikeb { 909fb5e93d4Smikeb struct iked_policy *pol; 910fb5e93d4Smikeb struct iked_flow *flow; 911fb5e93d4Smikeb off_t offset = 0; 912fb5e93d4Smikeb unsigned int id; 913fb5e93d4Smikeb uint8_t *buf = (uint8_t *)imsg->data; 914fb5e93d4Smikeb 915fb5e93d4Smikeb if (IMSG_DATA_SIZE(imsg) < sizeof(id)) 916fb5e93d4Smikeb fatalx("bad length imsg received"); 917fb5e93d4Smikeb 918fb5e93d4Smikeb memcpy(&id, buf, sizeof(id)); 919fb5e93d4Smikeb offset += sizeof(id); 920fb5e93d4Smikeb 921fb5e93d4Smikeb TAILQ_FOREACH(pol, &env->sc_policies, pol_entry) { 922fb5e93d4Smikeb if (pol->pol_id == id) 923fb5e93d4Smikeb break; 924fb5e93d4Smikeb } 925fb5e93d4Smikeb if (pol == NULL) { 926fb5e93d4Smikeb log_warnx("%s: unknown policy %u", __func__, id); 927fb5e93d4Smikeb return (-1); 928fb5e93d4Smikeb } 929fb5e93d4Smikeb 930fb5e93d4Smikeb if ((flow = calloc(1, sizeof(*flow))) == NULL) 931fb5e93d4Smikeb fatal("config_getpolicy: new flow"); 932fb5e93d4Smikeb 933fb5e93d4Smikeb memcpy(flow, buf + offset, sizeof(*flow)); 934fb5e93d4Smikeb 935fb5e93d4Smikeb if (RB_INSERT(iked_flows, &pol->pol_flows, flow)) { 936fb5e93d4Smikeb log_warnx("%s: received duplicate flow", __func__); 937fb5e93d4Smikeb free(flow); 938fb5e93d4Smikeb return (-1); 939fb5e93d4Smikeb } 940fb5e93d4Smikeb pol->pol_nflows++; 941fb5e93d4Smikeb 942fb5e93d4Smikeb return (0); 943fb5e93d4Smikeb } 944fb5e93d4Smikeb 945fb5e93d4Smikeb int 946f2f2a684Sreyk config_setcompile(struct iked *env, enum privsep_procid id) 947e2015428Sreyk { 948e2015428Sreyk if (env->sc_opts & IKED_OPT_NOACTION) 949e2015428Sreyk return (0); 950e2015428Sreyk 951c205e972Sreyk proc_compose(&env->sc_ps, id, IMSG_COMPILE, NULL, 0); 952e2015428Sreyk return (0); 953e2015428Sreyk } 954e2015428Sreyk 955e2015428Sreyk int 95658afaaa2Stobhe config_getcompile(struct iked *env) 957e2015428Sreyk { 958e2015428Sreyk /* 959e2015428Sreyk * Do any necessary steps after configuration, for now we 960e2015428Sreyk * only need to compile the skip steps. 961e2015428Sreyk */ 962e2015428Sreyk policy_calc_skip_steps(&env->sc_policies); 963e2015428Sreyk 964e2015428Sreyk log_debug("%s: compilation done", __func__); 965e2015428Sreyk return (0); 966e2015428Sreyk } 9676d3b905bSmarkus 9686d3b905bSmarkus int 969421819b6Stobhe config_setstatic(struct iked *env) 970c0b327e6Spatrick { 971421819b6Stobhe proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CTL_STATIC, 972421819b6Stobhe &env->sc_static, sizeof(env->sc_static)); 97373cd769dStobhe proc_compose(&env->sc_ps, PROC_CERT, IMSG_CTL_STATIC, 97473cd769dStobhe &env->sc_static, sizeof(env->sc_static)); 975c0b327e6Spatrick return (0); 976c0b327e6Spatrick } 977c0b327e6Spatrick 978c0b327e6Spatrick int 979421819b6Stobhe config_getstatic(struct iked *env, struct imsg *imsg) 980c0b327e6Spatrick { 981421819b6Stobhe IMSG_SIZE_CHECK(imsg, &env->sc_static); 982421819b6Stobhe memcpy(&env->sc_static, imsg->data, sizeof(env->sc_static)); 983c0b327e6Spatrick 98443d162a4Stobhe log_debug("%s: dpd_check_interval %llu", __func__, env->sc_alive_timeout); 985729f601bStobhe log_debug("%s: %senforcesingleikesa", __func__, 986729f601bStobhe env->sc_enforcesingleikesa ? "" : "no "); 987421819b6Stobhe log_debug("%s: %sfragmentation", __func__, env->sc_frag ? "" : "no "); 988421819b6Stobhe log_debug("%s: %smobike", __func__, env->sc_mobike ? "" : "no "); 989421819b6Stobhe log_debug("%s: nattport %u", __func__, env->sc_nattport); 990e3244f00Stobhe log_debug("%s: %sstickyaddress", __func__, 991e3244f00Stobhe env->sc_stickyaddress ? "" : "no "); 992421819b6Stobhe 9938ad617ceStobhe ikev2_reset_alive_timer(env); 9948ad617ceStobhe 995729f601bStobhe return (0); 996729f601bStobhe } 997729f601bStobhe 998729f601bStobhe int 9996d3b905bSmarkus config_setocsp(struct iked *env) 10006d3b905bSmarkus { 1001c973c574Stobhe struct iovec iov[3]; 1002c973c574Stobhe int iovcnt = 0; 1003c973c574Stobhe 10046d3b905bSmarkus if (env->sc_opts & IKED_OPT_NOACTION) 10056d3b905bSmarkus return (0); 10066d3b905bSmarkus 1007c973c574Stobhe iov[0].iov_base = &env->sc_ocsp_tolerate; 1008c973c574Stobhe iov[0].iov_len = sizeof(env->sc_ocsp_tolerate); 1009c973c574Stobhe iovcnt++; 1010c973c574Stobhe iov[1].iov_base = &env->sc_ocsp_maxage; 1011c973c574Stobhe iov[1].iov_len = sizeof(env->sc_ocsp_maxage); 1012c973c574Stobhe iovcnt++; 1013c973c574Stobhe if (env->sc_ocsp_url) { 1014c973c574Stobhe iov[2].iov_base = env->sc_ocsp_url; 1015c973c574Stobhe iov[2].iov_len = strlen(env->sc_ocsp_url); 1016c973c574Stobhe iovcnt++; 1017c973c574Stobhe } 1018c973c574Stobhe return (proc_composev(&env->sc_ps, PROC_CERT, IMSG_OCSP_CFG, 1019c973c574Stobhe iov, iovcnt)); 10206d3b905bSmarkus } 10216d3b905bSmarkus 10226d3b905bSmarkus int 10236d3b905bSmarkus config_getocsp(struct iked *env, struct imsg *imsg) 10246d3b905bSmarkus { 1025c973c574Stobhe size_t have, need; 1026229c27f0Stobhe uint8_t *ptr; 1027c973c574Stobhe 10286d3b905bSmarkus free(env->sc_ocsp_url); 1029229c27f0Stobhe ptr = (uint8_t *)imsg->data; 1030c973c574Stobhe have = IMSG_DATA_SIZE(imsg); 1031c973c574Stobhe 1032c973c574Stobhe /* get tolerate */ 1033c973c574Stobhe need = sizeof(env->sc_ocsp_tolerate); 1034c973c574Stobhe if (have < need) 1035c973c574Stobhe fatalx("bad 'tolerate' length imsg received"); 1036c973c574Stobhe memcpy(&env->sc_ocsp_tolerate, ptr, need); 1037c973c574Stobhe ptr += need; 1038c973c574Stobhe have -= need; 1039c973c574Stobhe 1040c973c574Stobhe /* get maxage */ 1041c973c574Stobhe need = sizeof(env->sc_ocsp_maxage); 1042c973c574Stobhe if (have < need) 1043c973c574Stobhe fatalx("bad 'maxage' length imsg received"); 1044c973c574Stobhe memcpy(&env->sc_ocsp_maxage, ptr, need); 1045c973c574Stobhe ptr += need; 1046c973c574Stobhe have -= need; 1047c973c574Stobhe 1048c973c574Stobhe /* get url */ 1049c973c574Stobhe if (have > 0) 1050c973c574Stobhe env->sc_ocsp_url = get_string(ptr, have); 10516d3b905bSmarkus else 10526d3b905bSmarkus env->sc_ocsp_url = NULL; 1053c973c574Stobhe log_debug("%s: ocsp_url %s tolerate %ld maxage %ld", __func__, 1054c973c574Stobhe env->sc_ocsp_url ? env->sc_ocsp_url : "none", 1055c973c574Stobhe env->sc_ocsp_tolerate, env->sc_ocsp_maxage); 10566d3b905bSmarkus return (0); 10576d3b905bSmarkus } 1058e8b444cdSreyk 1059e8b444cdSreyk int 1060e8b444cdSreyk config_setkeys(struct iked *env) 1061e8b444cdSreyk { 1062e8b444cdSreyk FILE *fp = NULL; 1063e8b444cdSreyk EVP_PKEY *key = NULL; 1064e8b444cdSreyk struct iked_id privkey; 1065e8b444cdSreyk struct iked_id pubkey; 1066e8b444cdSreyk struct iovec iov[2]; 1067e8b444cdSreyk int ret = -1; 1068e8b444cdSreyk 1069e8b444cdSreyk memset(&privkey, 0, sizeof(privkey)); 1070e8b444cdSreyk memset(&pubkey, 0, sizeof(pubkey)); 1071e8b444cdSreyk 1072e8b444cdSreyk /* Read private key */ 1073e8b444cdSreyk if ((fp = fopen(IKED_PRIVKEY, "r")) == NULL) { 1074e8b444cdSreyk log_warn("%s: failed to open private key", __func__); 1075e8b444cdSreyk goto done; 1076e8b444cdSreyk } 1077e8b444cdSreyk 1078e8b444cdSreyk if ((key = PEM_read_PrivateKey(fp, NULL, NULL, NULL)) == NULL) { 1079e8b444cdSreyk log_warnx("%s: failed to read private key", __func__); 1080e8b444cdSreyk goto done; 1081e8b444cdSreyk } 1082e8b444cdSreyk 1083e8b444cdSreyk if (ca_privkey_serialize(key, &privkey) != 0) { 1084e8b444cdSreyk log_warnx("%s: failed to serialize private key", __func__); 1085e8b444cdSreyk goto done; 1086e8b444cdSreyk } 1087e8b444cdSreyk if (ca_pubkey_serialize(key, &pubkey) != 0) { 1088e8b444cdSreyk log_warnx("%s: failed to serialize public key", __func__); 1089e8b444cdSreyk goto done; 1090e8b444cdSreyk } 1091e8b444cdSreyk 1092e8b444cdSreyk iov[0].iov_base = &privkey; 1093e8b444cdSreyk iov[0].iov_len = sizeof(privkey); 1094e8b444cdSreyk iov[1].iov_base = ibuf_data(privkey.id_buf); 1095eef6c82aSclaudio iov[1].iov_len = ibuf_size(privkey.id_buf); 1096e8b444cdSreyk 1097e8b444cdSreyk if (proc_composev(&env->sc_ps, PROC_CERT, IMSG_PRIVKEY, iov, 2) == -1) { 1098e8b444cdSreyk log_warnx("%s: failed to send private key", __func__); 1099e8b444cdSreyk goto done; 1100e8b444cdSreyk } 1101e8b444cdSreyk 1102e8b444cdSreyk iov[0].iov_base = &pubkey; 1103e8b444cdSreyk iov[0].iov_len = sizeof(pubkey); 1104e8b444cdSreyk iov[1].iov_base = ibuf_data(pubkey.id_buf); 1105eef6c82aSclaudio iov[1].iov_len = ibuf_size(pubkey.id_buf); 1106e8b444cdSreyk 1107e8b444cdSreyk if (proc_composev(&env->sc_ps, PROC_CERT, IMSG_PUBKEY, iov, 2) == -1) { 1108e8b444cdSreyk log_warnx("%s: failed to send public key", __func__); 1109e8b444cdSreyk goto done; 1110e8b444cdSreyk } 1111e8b444cdSreyk 1112e8b444cdSreyk ret = 0; 1113e8b444cdSreyk done: 1114e8b444cdSreyk if (fp != NULL) 1115e8b444cdSreyk fclose(fp); 1116e8b444cdSreyk 1117be2b38f5Sclaudio ibuf_free(pubkey.id_buf); 1118be2b38f5Sclaudio ibuf_free(privkey.id_buf); 1119e8b444cdSreyk EVP_PKEY_free(key); 1120e8b444cdSreyk 1121e8b444cdSreyk return (ret); 1122e8b444cdSreyk } 1123e8b444cdSreyk 1124e8b444cdSreyk int 1125e8b444cdSreyk config_getkey(struct iked *env, struct imsg *imsg) 1126e8b444cdSreyk { 1127e8b444cdSreyk size_t len; 1128e8b444cdSreyk struct iked_id id; 1129e8b444cdSreyk 1130e8b444cdSreyk len = IMSG_DATA_SIZE(imsg); 1131e8b444cdSreyk if (len <= sizeof(id)) 1132e8b444cdSreyk fatalx("%s: invalid key message", __func__); 1133e8b444cdSreyk 1134e8b444cdSreyk memcpy(&id, imsg->data, sizeof(id)); 1135e8b444cdSreyk if ((id.id_buf = ibuf_new((uint8_t *)imsg->data + sizeof(id), 1136e8b444cdSreyk len - sizeof(id))) == NULL) 1137e8b444cdSreyk fatalx("%s: failed to get key", __func__); 1138e8b444cdSreyk 1139e8b444cdSreyk explicit_bzero(imsg->data, len); 1140e8b444cdSreyk ca_getkey(&env->sc_ps, &id, imsg->hdr.type); 1141e8b444cdSreyk 1142e8b444cdSreyk return (0); 1143e8b444cdSreyk } 1144f36db9c4Syasuoka 1145f36db9c4Syasuoka int 1146f36db9c4Syasuoka config_setradauth(struct iked *env) 1147f36db9c4Syasuoka { 1148f36db9c4Syasuoka proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CFG_RADAUTH, 1149f36db9c4Syasuoka &env->sc_radauth, sizeof(env->sc_radauth)); 1150f36db9c4Syasuoka return (0); 1151f36db9c4Syasuoka } 1152f36db9c4Syasuoka 1153f36db9c4Syasuoka int 1154f36db9c4Syasuoka config_getradauth(struct iked *env, struct imsg *imsg) 1155f36db9c4Syasuoka { 1156f36db9c4Syasuoka if (IMSG_DATA_SIZE(imsg) < sizeof(struct iked_radopts)) 1157f36db9c4Syasuoka fatalx("%s: invalid radauth message", __func__); 1158f36db9c4Syasuoka 1159f36db9c4Syasuoka memcpy(&env->sc_radauth, imsg->data, sizeof(struct iked_radopts)); 1160f36db9c4Syasuoka 1161f36db9c4Syasuoka return (0); 1162f36db9c4Syasuoka } 1163f36db9c4Syasuoka 1164f36db9c4Syasuoka int 1165f36db9c4Syasuoka config_setradacct(struct iked *env) 1166f36db9c4Syasuoka { 1167f36db9c4Syasuoka proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CFG_RADACCT, 1168f36db9c4Syasuoka &env->sc_radacct, sizeof(env->sc_radacct)); 1169f36db9c4Syasuoka return (0); 1170f36db9c4Syasuoka } 1171f36db9c4Syasuoka 1172f36db9c4Syasuoka int 1173f36db9c4Syasuoka config_getradacct(struct iked *env, struct imsg *imsg) 1174f36db9c4Syasuoka { 1175f36db9c4Syasuoka if (IMSG_DATA_SIZE(imsg) < sizeof(struct iked_radopts)) 1176f36db9c4Syasuoka fatalx("%s: invalid radacct message", __func__); 1177f36db9c4Syasuoka 1178f36db9c4Syasuoka memcpy(&env->sc_radacct, imsg->data, sizeof(struct iked_radopts)); 1179f36db9c4Syasuoka 1180f36db9c4Syasuoka return (0); 1181f36db9c4Syasuoka } 1182f36db9c4Syasuoka 1183f36db9c4Syasuoka int 1184f36db9c4Syasuoka config_setradserver(struct iked *env, struct sockaddr *sa, socklen_t salen, 1185f36db9c4Syasuoka char *secret, int isaccounting) 1186f36db9c4Syasuoka { 1187f36db9c4Syasuoka int sock = -1; 1188f36db9c4Syasuoka struct iovec iov[2]; 1189f36db9c4Syasuoka struct iked_radserver server; 1190f36db9c4Syasuoka 1191f36db9c4Syasuoka if (env->sc_opts & IKED_OPT_NOACTION) 1192f36db9c4Syasuoka return (0); 1193f36db9c4Syasuoka memset(&server, 0, sizeof(server)); 1194f36db9c4Syasuoka memcpy(&server.rs_sockaddr, sa, salen); 1195f36db9c4Syasuoka server.rs_accounting = isaccounting; 1196f36db9c4Syasuoka if ((sock = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 1197f36db9c4Syasuoka log_warn("%s: socket() failed", __func__); 1198f36db9c4Syasuoka goto error; 1199f36db9c4Syasuoka } 1200f36db9c4Syasuoka if (connect(sock, sa, salen) == -1) { 1201f36db9c4Syasuoka log_warn("%s: connect() failed", __func__); 1202f36db9c4Syasuoka goto error; 1203f36db9c4Syasuoka } 1204f36db9c4Syasuoka iov[0].iov_base = &server; 1205f36db9c4Syasuoka iov[0].iov_len = offsetof(struct iked_radserver, rs_secret[0]); 1206f36db9c4Syasuoka iov[1].iov_base = secret; 1207f36db9c4Syasuoka iov[1].iov_len = strlen(secret) + 1; 1208f36db9c4Syasuoka 1209f36db9c4Syasuoka proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1, IMSG_CFG_RADSERVER, -1, 1210f36db9c4Syasuoka sock, iov, 2); 1211f36db9c4Syasuoka 1212f36db9c4Syasuoka return (0); 1213f36db9c4Syasuoka error: 1214f36db9c4Syasuoka if (sock >= 0) 1215f36db9c4Syasuoka close(sock); 1216f36db9c4Syasuoka return (-1); 1217f36db9c4Syasuoka } 1218f36db9c4Syasuoka 1219f36db9c4Syasuoka int 1220f36db9c4Syasuoka config_getradserver(struct iked *env, struct imsg *imsg) 1221f36db9c4Syasuoka { 1222f36db9c4Syasuoka size_t len; 1223f36db9c4Syasuoka struct iked_radserver *server; 1224f36db9c4Syasuoka 1225f36db9c4Syasuoka len = IMSG_DATA_SIZE(imsg); 1226f36db9c4Syasuoka if (len <= sizeof(*server)) 1227f36db9c4Syasuoka fatalx("%s: invalid IMSG_CFG_RADSERVER message", __func__); 1228f36db9c4Syasuoka 1229f36db9c4Syasuoka if ((server = calloc(1, len)) == NULL) { 1230f36db9c4Syasuoka log_warn("%s: calloc() failed", __func__); 1231f36db9c4Syasuoka return (-1); 1232f36db9c4Syasuoka } 1233f36db9c4Syasuoka memcpy(server, imsg->data, len); 1234f36db9c4Syasuoka explicit_bzero(imsg->data, len); 1235f36db9c4Syasuoka TAILQ_INIT(&server->rs_reqs); 1236f36db9c4Syasuoka server->rs_sock = imsg_get_fd(imsg); 1237f36db9c4Syasuoka server->rs_env = env; 1238f36db9c4Syasuoka 1239f36db9c4Syasuoka if (!server->rs_accounting) 1240f36db9c4Syasuoka TAILQ_INSERT_TAIL(&env->sc_radauthservers, server, rs_entry); 1241f36db9c4Syasuoka else 1242f36db9c4Syasuoka TAILQ_INSERT_TAIL(&env->sc_radacctservers, server, rs_entry); 1243f36db9c4Syasuoka event_set(&server->rs_ev, server->rs_sock, EV_READ | EV_PERSIST, 1244f36db9c4Syasuoka iked_radius_on_event, server); 1245f36db9c4Syasuoka event_add(&server->rs_ev, NULL); 1246f36db9c4Syasuoka 1247f36db9c4Syasuoka return (0); 1248f36db9c4Syasuoka } 1249f36db9c4Syasuoka 1250f36db9c4Syasuoka int 1251f36db9c4Syasuoka config_setradcfgmap(struct iked *env, int cfg_type, uint32_t vendor_id, 1252f36db9c4Syasuoka uint8_t attr_type) 1253f36db9c4Syasuoka { 1254f36db9c4Syasuoka struct iked_radcfgmap cfgmap; 1255f36db9c4Syasuoka 1256f36db9c4Syasuoka if (env->sc_opts & IKED_OPT_NOACTION) 1257f36db9c4Syasuoka return (0); 1258f36db9c4Syasuoka memset(&cfgmap, 0, sizeof(cfgmap)); 1259f36db9c4Syasuoka cfgmap.cfg_type = cfg_type; 1260f36db9c4Syasuoka cfgmap.vendor_id = vendor_id; 1261f36db9c4Syasuoka cfgmap.attr_type = attr_type; 1262f36db9c4Syasuoka 1263f36db9c4Syasuoka proc_compose_imsg(&env->sc_ps, PROC_IKEV2, -1, IMSG_CFG_RADCFGMAP, -1, 1264f36db9c4Syasuoka -1, &cfgmap, sizeof(cfgmap)); 1265f36db9c4Syasuoka 1266f36db9c4Syasuoka return (0); 1267f36db9c4Syasuoka } 1268f36db9c4Syasuoka 1269f36db9c4Syasuoka int 1270f36db9c4Syasuoka config_getradcfgmap(struct iked *env, struct imsg *imsg) 1271f36db9c4Syasuoka { 1272f36db9c4Syasuoka int i; 1273f36db9c4Syasuoka size_t len; 1274f36db9c4Syasuoka struct iked_radcfgmap *cfgmap, *cfgmap0; 1275f36db9c4Syasuoka struct iked_radcfgmaps cfgmaps = TAILQ_HEAD_INITIALIZER(cfgmaps); 1276f36db9c4Syasuoka 1277f36db9c4Syasuoka len = IMSG_DATA_SIZE(imsg); 1278f36db9c4Syasuoka if (len < sizeof(*cfgmap)) 1279f36db9c4Syasuoka fatalx("%s: invalid IMSG_CFG_RADCFGMAP message", __func__); 1280f36db9c4Syasuoka 1281f36db9c4Syasuoka if (TAILQ_EMPTY(&env->sc_radcfgmaps)) { 1282f36db9c4Syasuoka /* no customized config map yet */ 1283f36db9c4Syasuoka for (i = 0; radius_cfgmaps[i].cfg_type != 0; i++) { 1284f36db9c4Syasuoka if ((cfgmap = calloc(1, len)) == NULL) { 1285f36db9c4Syasuoka while ((cfgmap = TAILQ_FIRST(&cfgmaps)) 1286f36db9c4Syasuoka != NULL) { 1287f36db9c4Syasuoka TAILQ_REMOVE(&cfgmaps, cfgmap, entry); 1288f36db9c4Syasuoka free(cfgmap); 1289f36db9c4Syasuoka } 1290f36db9c4Syasuoka return (-1); 1291f36db9c4Syasuoka } 1292f36db9c4Syasuoka *cfgmap = radius_cfgmaps[i]; 1293f36db9c4Syasuoka TAILQ_INSERT_TAIL(&cfgmaps, cfgmap, entry); 1294f36db9c4Syasuoka } 1295f36db9c4Syasuoka TAILQ_CONCAT(&env->sc_radcfgmaps, &cfgmaps, entry); 1296f36db9c4Syasuoka } 1297f36db9c4Syasuoka 1298f36db9c4Syasuoka cfgmap0 = (struct iked_radcfgmap *)imsg->data; 1299f36db9c4Syasuoka TAILQ_FOREACH(cfgmap, &env->sc_radcfgmaps, entry) { 1300f36db9c4Syasuoka if (cfgmap->vendor_id == cfgmap0->vendor_id && 1301f36db9c4Syasuoka cfgmap->attr_type == cfgmap0->attr_type) { 1302f36db9c4Syasuoka /* override existing config map */ 1303f36db9c4Syasuoka cfgmap->cfg_type = cfgmap0->cfg_type; 1304f36db9c4Syasuoka break; 1305f36db9c4Syasuoka } 1306f36db9c4Syasuoka } 1307f36db9c4Syasuoka if (cfgmap == NULL) { 1308f36db9c4Syasuoka if ((cfgmap = calloc(1, len)) == NULL) { 1309f36db9c4Syasuoka log_warn("%s: calloc() failed", __func__); 1310f36db9c4Syasuoka return (-1); 1311f36db9c4Syasuoka } 1312f36db9c4Syasuoka memcpy(cfgmap, imsg->data, len); 1313f36db9c4Syasuoka TAILQ_INSERT_TAIL(&env->sc_radcfgmaps, cfgmap, entry); 1314f36db9c4Syasuoka } 1315f36db9c4Syasuoka return (0); 1316f36db9c4Syasuoka } 1317f36db9c4Syasuoka 1318f36db9c4Syasuoka int 1319f36db9c4Syasuoka config_setraddae(struct iked *env, struct sockaddr *sa, socklen_t salen) 1320f36db9c4Syasuoka { 1321f36db9c4Syasuoka int sock, on; 1322f36db9c4Syasuoka struct iked_raddae dae; 1323f36db9c4Syasuoka 1324f36db9c4Syasuoka if (env->sc_opts & IKED_OPT_NOACTION) 1325f36db9c4Syasuoka return (0); 1326f36db9c4Syasuoka memset(&dae, 0, sizeof(dae)); 1327f36db9c4Syasuoka memcpy(&dae.rd_sockaddr, sa, salen); 1328f36db9c4Syasuoka if ((sock = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 1329f36db9c4Syasuoka log_warn("%s: socket() failed", __func__); 1330f36db9c4Syasuoka goto error; 1331f36db9c4Syasuoka } 1332f36db9c4Syasuoka on = 1; 1333f36db9c4Syasuoka if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) 1334f36db9c4Syasuoka log_warn("%s: setsockopt(,,SO_REUSEADDR) failed", __func__); 1335f36db9c4Syasuoka /* REUSEPORT is needed because the old sockets may not be closed yet */ 1336f36db9c4Syasuoka on = 1; 1337f36db9c4Syasuoka if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) == -1) 1338f36db9c4Syasuoka log_warn("%s: setsockopt(,,SO_REUSEPORT) failed", __func__); 1339f36db9c4Syasuoka if (bind(sock, sa, salen) == -1) { 1340f36db9c4Syasuoka log_warn("%s: bind() failed", __func__); 1341f36db9c4Syasuoka goto error; 1342f36db9c4Syasuoka } 1343f36db9c4Syasuoka 1344f36db9c4Syasuoka proc_compose_imsg(&env->sc_ps, PROC_IKEV2, -1, IMSG_CFG_RADDAE, -1, 1345f36db9c4Syasuoka sock, &dae, sizeof(dae)); 1346f36db9c4Syasuoka 1347f36db9c4Syasuoka return (0); 1348f36db9c4Syasuoka error: 1349f36db9c4Syasuoka if (sock >= 0) 1350f36db9c4Syasuoka close(sock); 1351f36db9c4Syasuoka return (-1); 1352f36db9c4Syasuoka } 1353f36db9c4Syasuoka 1354f36db9c4Syasuoka int 1355f36db9c4Syasuoka config_getraddae(struct iked *env, struct imsg *imsg) 1356f36db9c4Syasuoka { 1357f36db9c4Syasuoka struct iked_raddae *dae; 1358f36db9c4Syasuoka 1359f36db9c4Syasuoka if (IMSG_DATA_SIZE(imsg) < sizeof(*dae)) 1360f36db9c4Syasuoka fatalx("%s: invalid IMSG_CFG_RADDAE message", __func__); 1361f36db9c4Syasuoka 1362f36db9c4Syasuoka if ((dae = calloc(1, sizeof(*dae))) == NULL) { 1363f36db9c4Syasuoka log_warn("%s: calloc() failed", __func__); 1364f36db9c4Syasuoka return (-1); 1365f36db9c4Syasuoka } 1366f36db9c4Syasuoka memcpy(dae, imsg->data, sizeof(*dae)); 1367f36db9c4Syasuoka dae->rd_sock = imsg_get_fd(imsg); 1368f36db9c4Syasuoka dae->rd_env = env; 1369f36db9c4Syasuoka 1370f36db9c4Syasuoka event_set(&dae->rd_ev, dae->rd_sock, EV_READ | EV_PERSIST, 1371f36db9c4Syasuoka iked_radius_dae_on_event, dae); 1372f36db9c4Syasuoka event_add(&dae->rd_ev, NULL); 1373f36db9c4Syasuoka 1374f36db9c4Syasuoka TAILQ_INSERT_TAIL(&env->sc_raddaes, dae, rd_entry); 1375f36db9c4Syasuoka 1376f36db9c4Syasuoka return (0); 1377f36db9c4Syasuoka } 1378f36db9c4Syasuoka 1379f36db9c4Syasuoka int 1380f36db9c4Syasuoka config_setradclient(struct iked *env, struct sockaddr *sa, socklen_t salen, 1381f36db9c4Syasuoka char *secret) 1382f36db9c4Syasuoka { 1383f36db9c4Syasuoka struct iovec iov[2]; 1384f36db9c4Syasuoka struct iked_radclient client; 1385f36db9c4Syasuoka 1386f36db9c4Syasuoka if (salen > sizeof(client.rc_sockaddr)) 1387f36db9c4Syasuoka fatal("%s: invalid salen", __func__); 1388f36db9c4Syasuoka 1389f36db9c4Syasuoka memcpy(&client.rc_sockaddr, sa, salen); 1390f36db9c4Syasuoka 1391f36db9c4Syasuoka iov[0].iov_base = &client; 1392f36db9c4Syasuoka iov[0].iov_len = offsetof(struct iked_radclient, rc_secret[0]); 1393f36db9c4Syasuoka iov[1].iov_base = secret; 1394f36db9c4Syasuoka iov[1].iov_len = strlen(secret); 1395f36db9c4Syasuoka 1396f36db9c4Syasuoka proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1, IMSG_CFG_RADDAECLIENT, 1397f36db9c4Syasuoka -1, -1, iov, 2); 1398f36db9c4Syasuoka 1399f36db9c4Syasuoka return (0); 1400f36db9c4Syasuoka } 1401f36db9c4Syasuoka 1402f36db9c4Syasuoka int 1403f36db9c4Syasuoka config_getradclient(struct iked *env, struct imsg *imsg) 1404f36db9c4Syasuoka { 1405f36db9c4Syasuoka struct iked_radclient *client; 1406f36db9c4Syasuoka u_int len; 1407f36db9c4Syasuoka 1408f36db9c4Syasuoka len = IMSG_DATA_SIZE(imsg); 1409f36db9c4Syasuoka 1410f36db9c4Syasuoka if (len < sizeof(*client)) 1411f36db9c4Syasuoka fatalx("%s: invalid IMSG_CFG_RADDAE message", __func__); 1412f36db9c4Syasuoka 1413f36db9c4Syasuoka if ((client = calloc(1, len + 1)) == NULL) { 1414f36db9c4Syasuoka log_warn("%s: calloc() failed", __func__); 1415f36db9c4Syasuoka return (-1); 1416f36db9c4Syasuoka } 1417f36db9c4Syasuoka memcpy(client, imsg->data, len); 1418f36db9c4Syasuoka 1419f36db9c4Syasuoka TAILQ_INSERT_TAIL(&env->sc_raddaeclients, client, rc_entry); 1420f36db9c4Syasuoka 1421f36db9c4Syasuoka return (0); 1422f36db9c4Syasuoka } 1423