1/* 2 * Copyright (C) 2001-2003 by Darren Reed 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT 7 * code. 8 * 9 * $Id: ip_ipsec_pxy.c,v 2.20.2.8 2006/07/14 06:12:14 darrenr Exp $ 10 * 11 */ 12#define IPF_IPSEC_PROXY 13 14 15int ippr_ipsec_init __P((void)); 16void ippr_ipsec_fini __P((void)); 17int ippr_ipsec_new __P((fr_info_t *, ap_session_t *, nat_t *)); 18void ippr_ipsec_del __P((ap_session_t *)); 19int ippr_ipsec_inout __P((fr_info_t *, ap_session_t *, nat_t *)); 20int ippr_ipsec_match __P((fr_info_t *, ap_session_t *, nat_t *)); 21 22static frentry_t ipsecfr; 23static ipftq_t *ipsecnattqe; 24static ipftq_t *ipsecstatetqe; 25static char ipsec_buffer[1500]; 26 27int ipsec_proxy_init = 0; 28int ipsec_proxy_ttl = 60; 29 30/* 31 * IPSec application proxy initialization. 32 */ 33int ippr_ipsec_init() 34{ 35 bzero((char *)&ipsecfr, sizeof(ipsecfr)); 36 ipsecfr.fr_ref = 1; 37 ipsecfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; 38 MUTEX_INIT(&ipsecfr.fr_lock, "IPsec proxy rule lock"); 39 ipsec_proxy_init = 1; 40 41 ipsecnattqe = fr_addtimeoutqueue(&nat_utqe, ipsec_proxy_ttl); 42 if (ipsecnattqe == NULL) 43 return -1; 44 ipsecstatetqe = fr_addtimeoutqueue(&ips_utqe, ipsec_proxy_ttl); 45 if (ipsecstatetqe == NULL) { 46 if (fr_deletetimeoutqueue(ipsecnattqe) == 0) 47 fr_freetimeoutqueue(ipsecnattqe); 48 ipsecnattqe = NULL; 49 return -1; 50 } 51 52 ipsecnattqe->ifq_flags |= IFQF_PROXY; 53 ipsecstatetqe->ifq_flags |= IFQF_PROXY; 54 55 ipsecfr.fr_age[0] = ipsec_proxy_ttl; 56 ipsecfr.fr_age[1] = ipsec_proxy_ttl; 57 return 0; 58} 59 60 61void ippr_ipsec_fini() 62{ 63 if (ipsecnattqe != NULL) { 64 if (fr_deletetimeoutqueue(ipsecnattqe) == 0) 65 fr_freetimeoutqueue(ipsecnattqe); 66 } 67 ipsecnattqe = NULL; 68 if (ipsecstatetqe != NULL) { 69 if (fr_deletetimeoutqueue(ipsecstatetqe) == 0) 70 fr_freetimeoutqueue(ipsecstatetqe); 71 } 72 ipsecstatetqe = NULL; 73 74 if (ipsec_proxy_init == 1) { 75 MUTEX_DESTROY(&ipsecfr.fr_lock); 76 ipsec_proxy_init = 0; 77 } 78} 79 80 81/* 82 * Setup for a new IPSEC proxy. 83 */ 84int ippr_ipsec_new(fin, aps, nat) 85fr_info_t *fin; 86ap_session_t *aps; 87nat_t *nat; 88{ 89 ipsec_pxy_t *ipsec; 90 fr_info_t fi; 91 ipnat_t *ipn; 92 char *ptr; 93 int p, off, dlen, ttl; 94 mb_t *m; 95 ip_t *ip; 96 97 off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff; 98 bzero(ipsec_buffer, sizeof(ipsec_buffer)); 99 ip = fin->fin_ip; 100 m = fin->fin_m; 101 102 dlen = M_LEN(m) - off; 103 if (dlen < 16) 104 return -1; 105 COPYDATA(m, off, MIN(sizeof(ipsec_buffer), dlen), ipsec_buffer); 106 107 if (nat_outlookup(fin, 0, IPPROTO_ESP, nat->nat_inip, 108 ip->ip_dst) != NULL) 109 return -1; 110 111 aps->aps_psiz = sizeof(*ipsec); 112 KMALLOCS(aps->aps_data, ipsec_pxy_t *, sizeof(*ipsec)); 113 if (aps->aps_data == NULL) 114 return -1; 115 116 ipsec = aps->aps_data; 117 bzero((char *)ipsec, sizeof(*ipsec)); 118 119 /* 120 * Create NAT rule against which the tunnel/transport mapping is 121 * created. This is required because the current NAT rule does not 122 * describe ESP but UDP instead. 123 */ 124 ipn = &ipsec->ipsc_rule; 125 ttl = IPF_TTLVAL(ipsecnattqe->ifq_ttl); 126 ipn->in_tqehead[0] = fr_addtimeoutqueue(&nat_utqe, ttl); 127 ipn->in_tqehead[1] = fr_addtimeoutqueue(&nat_utqe, ttl); 128 ipn->in_ifps[0] = fin->fin_ifp; 129 ipn->in_apr = NULL; 130 ipn->in_use = 1; 131 ipn->in_hits = 1; 132 ipn->in_nip = ntohl(nat->nat_outip.s_addr); 133 ipn->in_ippip = 1; 134 ipn->in_inip = nat->nat_inip.s_addr; 135 ipn->in_inmsk = 0xffffffff; 136 ipn->in_outip = fin->fin_saddr; 137 ipn->in_outmsk = nat->nat_outip.s_addr; 138 ipn->in_srcip = fin->fin_saddr; 139 ipn->in_srcmsk = 0xffffffff; 140 ipn->in_redir = NAT_MAP; 141 bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0], 142 sizeof(ipn->in_ifnames[0])); 143 ipn->in_p = IPPROTO_ESP; 144 145 bcopy((char *)fin, (char *)&fi, sizeof(fi)); 146 fi.fin_state = NULL; 147 fi.fin_nat = NULL; 148 fi.fin_fi.fi_p = IPPROTO_ESP; 149 fi.fin_fr = &ipsecfr; 150 fi.fin_data[0] = 0; 151 fi.fin_data[1] = 0; 152 p = ip->ip_p; 153 ip->ip_p = IPPROTO_ESP; 154 fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); 155 fi.fin_flx |= FI_IGNORE; 156 157 ptr = ipsec_buffer; 158 bcopy(ptr, (char *)ipsec->ipsc_icookie, sizeof(ipsec_cookie_t)); 159 ptr += sizeof(ipsec_cookie_t); 160 bcopy(ptr, (char *)ipsec->ipsc_rcookie, sizeof(ipsec_cookie_t)); 161 /* 162 * The responder cookie should only be non-zero if the initiator 163 * cookie is non-zero. Therefore, it is safe to assume(!) that the 164 * cookies are both set after copying if the responder is non-zero. 165 */ 166 if ((ipsec->ipsc_rcookie[0]|ipsec->ipsc_rcookie[1]) != 0) 167 ipsec->ipsc_rckset = 1; 168 169 ipsec->ipsc_nat = nat_new(&fi, ipn, &ipsec->ipsc_nat, 170 NAT_SLAVE|SI_WILDP, NAT_OUTBOUND); 171 if (ipsec->ipsc_nat != NULL) { 172 (void) nat_proto(&fi, ipsec->ipsc_nat, 0); 173 nat_update(&fi, ipsec->ipsc_nat, ipn); 174 175 fi.fin_data[0] = 0; 176 fi.fin_data[1] = 0; 177 ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state, 178 SI_WILDP); 179 if (fi.fin_state != NULL) 180 fr_statederef((ipstate_t **)&fi.fin_state); 181 } 182 ip->ip_p = p & 0xff; 183 return 0; 184} 185 186 187/* 188 * For outgoing IKE packets. refresh timeouts for NAT & state entries, if 189 * we can. If they have disappeared, recreate them. 190 */ 191int ippr_ipsec_inout(fin, aps, nat) 192fr_info_t *fin; 193ap_session_t *aps; 194nat_t *nat; 195{ 196 ipsec_pxy_t *ipsec; 197 fr_info_t fi; 198 ip_t *ip; 199 int p; 200 201 if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND)) 202 return 0; 203 204 if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND)) 205 return 0; 206 207 ipsec = aps->aps_data; 208 209 if (ipsec != NULL) { 210 ip = fin->fin_ip; 211 p = ip->ip_p; 212 213 if ((ipsec->ipsc_nat == NULL) || (ipsec->ipsc_state == NULL)) { 214 bcopy((char *)fin, (char *)&fi, sizeof(fi)); 215 fi.fin_state = NULL; 216 fi.fin_nat = NULL; 217 fi.fin_fi.fi_p = IPPROTO_ESP; 218 fi.fin_fr = &ipsecfr; 219 fi.fin_data[0] = 0; 220 fi.fin_data[1] = 0; 221 ip->ip_p = IPPROTO_ESP; 222 fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); 223 fi.fin_flx |= FI_IGNORE; 224 } 225 226 /* 227 * Update NAT timeout/create NAT if missing. 228 */ 229 if (ipsec->ipsc_nat != NULL) 230 fr_queueback(&ipsec->ipsc_nat->nat_tqe); 231 else { 232 ipsec->ipsc_nat = nat_new(&fi, &ipsec->ipsc_rule, 233 &ipsec->ipsc_nat, 234 NAT_SLAVE|SI_WILDP, 235 nat->nat_dir); 236 if (ipsec->ipsc_nat != NULL) { 237 (void) nat_proto(&fi, ipsec->ipsc_nat, 0); 238 nat_update(&fi, ipsec->ipsc_nat, 239 &ipsec->ipsc_rule); 240 } 241 } 242 243 /* 244 * Update state timeout/create state if missing. 245 */ 246 READ_ENTER(&ipf_state); 247 if (ipsec->ipsc_state != NULL) { 248 fr_queueback(&ipsec->ipsc_state->is_sti); 249 ipsec->ipsc_state->is_die = nat->nat_age; 250 RWLOCK_EXIT(&ipf_state); 251 } else { 252 RWLOCK_EXIT(&ipf_state); 253 fi.fin_data[0] = 0; 254 fi.fin_data[1] = 0; 255 ipsec->ipsc_state = fr_addstate(&fi, 256 &ipsec->ipsc_state, 257 SI_WILDP); 258 if (fi.fin_state != NULL) 259 fr_statederef((ipstate_t **)&fi.fin_state); 260 } 261 ip->ip_p = p; 262 } 263 return 0; 264} 265 266 267/* 268 * This extends the NAT matching to be based on the cookies associated with 269 * a session and found at the front of IKE packets. The cookies are always 270 * in the same order (not reversed depending on packet flow direction as with 271 * UDP/TCP port numbers). 272 */ 273int ippr_ipsec_match(fin, aps, nat) 274fr_info_t *fin; 275ap_session_t *aps; 276nat_t *nat; 277{ 278 ipsec_pxy_t *ipsec; 279 u_32_t cookies[4]; 280 mb_t *m; 281 int off; 282 283 nat = nat; /* LINT */ 284 285 if ((fin->fin_dlen < sizeof(cookies)) || (fin->fin_flx & FI_FRAG)) 286 return -1; 287 288 off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff; 289 ipsec = aps->aps_data; 290 m = fin->fin_m; 291 COPYDATA(m, off, sizeof(cookies), (char *)cookies); 292 293 if ((cookies[0] != ipsec->ipsc_icookie[0]) || 294 (cookies[1] != ipsec->ipsc_icookie[1])) 295 return -1; 296 297 if (ipsec->ipsc_rckset == 0) { 298 if ((cookies[2]|cookies[3]) == 0) { 299 return 0; 300 } 301 ipsec->ipsc_rckset = 1; 302 ipsec->ipsc_rcookie[0] = cookies[2]; 303 ipsec->ipsc_rcookie[1] = cookies[3]; 304 return 0; 305 } 306 307 if ((cookies[2] != ipsec->ipsc_rcookie[0]) || 308 (cookies[3] != ipsec->ipsc_rcookie[1])) 309 return -1; 310 return 0; 311} 312 313 314/* 315 * clean up after ourselves. 316 */ 317void ippr_ipsec_del(aps) 318ap_session_t *aps; 319{ 320 ipsec_pxy_t *ipsec; 321 322 ipsec = aps->aps_data; 323 324 if (ipsec != NULL) { 325 /* 326 * Don't bother changing any of the NAT structure details, 327 * *_del() is on a callback from aps_free(), from nat_delete() 328 */ 329 330 READ_ENTER(&ipf_state); 331 if (ipsec->ipsc_state != NULL) { 332 ipsec->ipsc_state->is_die = fr_ticks + 1; 333 ipsec->ipsc_state->is_me = NULL; 334 fr_queuefront(&ipsec->ipsc_state->is_sti); 335 } 336 RWLOCK_EXIT(&ipf_state); 337 338 ipsec->ipsc_state = NULL; 339 ipsec->ipsc_nat = NULL; 340 } 341} 342