1/* 2 * Copyright (C) 2012 by Darren Reed. 3 * 4 * Simple PPTP transparent proxy for in-kernel use. For use with the NAT 5 * code. 6 * 7 * $Id$ 8 * 9 */ 10#define IPF_PPTP_PROXY 11 12 13 14/* 15 * PPTP proxy 16 */ 17typedef struct pptp_side { 18 u_32_t pptps_nexthdr; 19 u_32_t pptps_next; 20 int pptps_state; 21 int pptps_gothdr; 22 int pptps_len; 23 int pptps_bytes; 24 char *pptps_wptr; 25 char pptps_buffer[512]; 26} pptp_side_t; 27 28typedef struct pptp_pxy { 29 nat_t *pptp_nat; 30 struct ipstate *pptp_state; 31 u_short pptp_call[2]; 32 pptp_side_t pptp_side[2]; 33 ipnat_t *pptp_rule; 34} pptp_pxy_t; 35 36typedef struct pptp_hdr { 37 u_short pptph_len; 38 u_short pptph_type; 39 u_32_t pptph_cookie; 40} pptp_hdr_t; 41 42#define PPTP_MSGTYPE_CTL 1 43#define PPTP_MTCTL_STARTREQ 1 44#define PPTP_MTCTL_STARTREP 2 45#define PPTP_MTCTL_STOPREQ 3 46#define PPTP_MTCTL_STOPREP 4 47#define PPTP_MTCTL_ECHOREQ 5 48#define PPTP_MTCTL_ECHOREP 6 49#define PPTP_MTCTL_OUTREQ 7 50#define PPTP_MTCTL_OUTREP 8 51#define PPTP_MTCTL_INREQ 9 52#define PPTP_MTCTL_INREP 10 53#define PPTP_MTCTL_INCONNECT 11 54#define PPTP_MTCTL_CLEAR 12 55#define PPTP_MTCTL_DISCONNECT 13 56#define PPTP_MTCTL_WANERROR 14 57#define PPTP_MTCTL_LINKINFO 15 58 59 60void ipf_p_pptp_main_load(void); 61void ipf_p_pptp_main_unload(void); 62int ipf_p_pptp_new(void *, fr_info_t *, ap_session_t *, nat_t *); 63void ipf_p_pptp_del(ipf_main_softc_t *, ap_session_t *); 64int ipf_p_pptp_inout(void *, fr_info_t *, ap_session_t *, nat_t *); 65void ipf_p_pptp_donatstate(fr_info_t *, nat_t *, pptp_pxy_t *); 66int ipf_p_pptp_message(fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *); 67int ipf_p_pptp_nextmessage(fr_info_t *, nat_t *, pptp_pxy_t *, int); 68int ipf_p_pptp_mctl(fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *); 69 70static frentry_t pptpfr; 71 72static int pptp_proxy_init = 0; 73static int ipf_p_pptp_debug = 0; 74static int ipf_p_pptp_gretimeout = IPF_TTLVAL(120); /* 2 minutes */ 75 76 77/* 78 * PPTP application proxy initialization. 79 */ 80void 81ipf_p_pptp_main_load(void) 82{ 83 bzero((char *)&pptpfr, sizeof(pptpfr)); 84 pptpfr.fr_ref = 1; 85 pptpfr.fr_age[0] = ipf_p_pptp_gretimeout; 86 pptpfr.fr_age[1] = ipf_p_pptp_gretimeout; 87 pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; 88 MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock"); 89 pptp_proxy_init = 1; 90} 91 92 93void 94ipf_p_pptp_main_unload(void) 95{ 96 if (pptp_proxy_init == 1) { 97 MUTEX_DESTROY(&pptpfr.fr_lock); 98 pptp_proxy_init = 0; 99 } 100} 101 102 103/* 104 * Setup for a new PPTP proxy. 105 * 106 * NOTE: The printf's are broken up with %s in them to prevent them being 107 * optimised into puts statements on FreeBSD (this doesn't exist in the kernel) 108 */ 109int 110ipf_p_pptp_new(void *arg, fr_info_t *fin, ap_session_t *aps, nat_t *nat) 111{ 112 pptp_pxy_t *pptp; 113 ipnat_t *ipn; 114 ipnat_t *np; 115 int size; 116 ip_t *ip; 117 118 if (fin->fin_v != 4) 119 return (-1); 120 121 ip = fin->fin_ip; 122 np = nat->nat_ptr; 123 size = np->in_size; 124 125 if (ipf_nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_osrcip, 126 ip->ip_dst) != NULL) { 127 if (ipf_p_pptp_debug > 0) 128 printf("ipf_p_pptp_new: GRE session already exists\n"); 129 return (-1); 130 } 131 132 KMALLOC(pptp, pptp_pxy_t *); 133 if (pptp == NULL) { 134 if (ipf_p_pptp_debug > 0) 135 printf("ipf_p_pptp_new: malloc for aps_data failed\n"); 136 return (-1); 137 } 138 KMALLOCS(ipn, ipnat_t *, size); 139 if (ipn == NULL) { 140 KFREE(pptp); 141 return (-1); 142 } 143 144 aps->aps_data = pptp; 145 aps->aps_psiz = sizeof(*pptp); 146 bzero((char *)pptp, sizeof(*pptp)); 147 bzero((char *)ipn, size); 148 pptp->pptp_rule = ipn; 149 150 /* 151 * Create NAT rule against which the tunnel/transport mapping is 152 * created. This is required because the current NAT rule does not 153 * describe GRE but TCP instead. 154 */ 155 ipn->in_size = size; 156 ipn->in_ifps[0] = fin->fin_ifp; 157 ipn->in_apr = NULL; 158 ipn->in_use = 1; 159 ipn->in_hits = 1; 160 ipn->in_ippip = 1; 161 ipn->in_snip = ntohl(nat->nat_nsrcaddr); 162 ipn->in_nsrcaddr = fin->fin_saddr; 163 ipn->in_dnip = ntohl(nat->nat_ndstaddr); 164 ipn->in_ndstaddr = nat->nat_ndstaddr; 165 ipn->in_redir = np->in_redir; 166 ipn->in_osrcaddr = nat->nat_osrcaddr; 167 ipn->in_odstaddr = nat->nat_odstaddr; 168 ipn->in_osrcmsk = 0xffffffff; 169 ipn->in_nsrcmsk = 0xffffffff; 170 ipn->in_odstmsk = 0xffffffff; 171 ipn->in_ndstmsk = 0xffffffff; 172 ipn->in_flags = (np->in_flags | IPN_PROXYRULE); 173 MUTEX_INIT(&ipn->in_lock, "pptp proxy NAT rule"); 174 175 ipn->in_namelen = np->in_namelen; 176 bcopy(np->in_names, ipn->in_ifnames, ipn->in_namelen); 177 ipn->in_ifnames[0] = np->in_ifnames[0]; 178 ipn->in_ifnames[1] = np->in_ifnames[1]; 179 180 ipn->in_pr[0] = IPPROTO_GRE; 181 ipn->in_pr[1] = IPPROTO_GRE; 182 183 pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer; 184 pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer; 185 return (0); 186} 187 188 189void 190ipf_p_pptp_donatstate(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp) 191{ 192 ipf_main_softc_t *softc = fin->fin_main_soft; 193 fr_info_t fi; 194 grehdr_t gre; 195 nat_t *nat2; 196 u_char p; 197 ip_t *ip; 198 199 ip = fin->fin_ip; 200 p = ip->ip_p; 201 202 nat2 = pptp->pptp_nat; 203 if ((nat2 == NULL) || (pptp->pptp_state == NULL)) { 204 bcopy((char *)fin, (char *)&fi, sizeof(fi)); 205 bzero((char *)&gre, sizeof(gre)); 206 fi.fin_fi.fi_p = IPPROTO_GRE; 207 fi.fin_fr = &pptpfr; 208 if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) || 209 (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) { 210 fi.fin_data[0] = pptp->pptp_call[0]; 211 fi.fin_data[1] = pptp->pptp_call[1]; 212 } else { 213 fi.fin_data[0] = pptp->pptp_call[1]; 214 fi.fin_data[1] = pptp->pptp_call[0]; 215 } 216 ip = fin->fin_ip; 217 ip->ip_p = IPPROTO_GRE; 218 fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); 219 fi.fin_flx |= FI_IGNORE; 220 fi.fin_dp = &gre; 221 gre.gr_flags = htons(1 << 13); 222 223 fi.fin_fi.fi_saddr = nat->nat_osrcaddr; 224 fi.fin_fi.fi_daddr = nat->nat_odstaddr; 225 } 226 227 /* 228 * Update NAT timeout/create NAT if missing. 229 */ 230 if (nat2 != NULL) 231 ipf_queueback(softc->ipf_ticks, &nat2->nat_tqe); 232 else { 233#ifdef USE_MUTEXES 234 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 235#endif 236 237 MUTEX_ENTER(&softn->ipf_nat_new); 238 nat2 = ipf_nat_add(&fi, pptp->pptp_rule, &pptp->pptp_nat, 239 NAT_SLAVE, nat->nat_dir); 240 MUTEX_EXIT(&softn->ipf_nat_new); 241 if (nat2 != NULL) { 242 (void) ipf_nat_proto(&fi, nat2, 0); 243 MUTEX_ENTER(&nat2->nat_lock); 244 ipf_nat_update(&fi, nat2); 245 MUTEX_EXIT(&nat2->nat_lock); 246 } 247 } 248 249 READ_ENTER(&softc->ipf_state); 250 if (pptp->pptp_state != NULL) { 251 ipf_queueback(softc->ipf_ticks, &pptp->pptp_state->is_sti); 252 RWLOCK_EXIT(&softc->ipf_state); 253 } else { 254 RWLOCK_EXIT(&softc->ipf_state); 255 if (nat2 != NULL) { 256 if (nat->nat_dir == NAT_INBOUND) 257 fi.fin_fi.fi_daddr = nat2->nat_ndstaddr; 258 else 259 fi.fin_fi.fi_saddr = nat2->nat_osrcaddr; 260 } 261 fi.fin_ifp = NULL; 262 (void) ipf_state_add(softc, &fi, &pptp->pptp_state, 0); 263 } 264 ip->ip_p = p; 265 return; 266} 267 268 269/* 270 * Try and build up the next PPTP message in the TCP stream and if we can 271 * build it up completely (fits in our buffer) then pass it off to the message 272 * parsing function. 273 */ 274int 275ipf_p_pptp_nextmessage(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp, int rev) 276{ 277 static const char *funcname = "ipf_p_pptp_nextmessage"; 278 pptp_side_t *pptps; 279 u_32_t start, end; 280 pptp_hdr_t *hdr; 281 tcphdr_t *tcp; 282 int dlen, off; 283 u_short len; 284 char *msg; 285 286 tcp = fin->fin_dp; 287 dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); 288 start = ntohl(tcp->th_seq); 289 pptps = &pptp->pptp_side[rev]; 290 off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) + 291 fin->fin_ipoff; 292 293 if (dlen <= 0) 294 return (0); 295 /* 296 * If the complete data packet is before what we expect to see 297 * "next", just ignore it as the chances are we've already seen it. 298 * The next if statement following this one really just causes packets 299 * ahead of what we've seen to be dropped, implying that something in 300 * the middle went missing and we want to see that first. 301 */ 302 end = start + dlen; 303 if (pptps->pptps_next > end && pptps->pptps_next > start) 304 return (0); 305 306 if (pptps->pptps_next != start) { 307 if (ipf_p_pptp_debug > 5) 308 printf("%s: next (%x) != start (%x)\n", funcname, 309 pptps->pptps_next, start); 310 return (-1); 311 } 312 313 msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2); 314 315 while (dlen > 0) { 316 off += pptps->pptps_bytes; 317 if (pptps->pptps_gothdr == 0) { 318 /* 319 * PPTP has an 8 byte header that inclues the cookie. 320 * The start of every message should include one and 321 * it should match 1a2b3c4d. Byte order is ignored, 322 * deliberately, when printing out the error. 323 */ 324 len = MIN(8 - pptps->pptps_bytes, dlen); 325 COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr); 326 pptps->pptps_bytes += len; 327 pptps->pptps_wptr += len; 328 hdr = (pptp_hdr_t *)pptps->pptps_buffer; 329 if (pptps->pptps_bytes == 8) { 330 pptps->pptps_next += 8; 331 if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) { 332 if (ipf_p_pptp_debug > 1) 333 printf("%s: bad cookie (%x)\n", 334 funcname, 335 hdr->pptph_cookie); 336 return (-1); 337 } 338 } 339 dlen -= len; 340 msg += len; 341 off += len; 342 343 pptps->pptps_gothdr = 1; 344 len = ntohs(hdr->pptph_len); 345 pptps->pptps_len = len; 346 pptps->pptps_nexthdr += len; 347 348 /* 349 * If a message is too big for the buffer, just set 350 * the fields for the next message to come along. 351 * The messages defined in RFC 2637 will not exceed 352 * 512 bytes (in total length) so this is likely a 353 * bad data packet, anyway. 354 */ 355 if (len > sizeof(pptps->pptps_buffer)) { 356 if (ipf_p_pptp_debug > 3) 357 printf("%s: message too big (%d)\n", 358 funcname, len); 359 pptps->pptps_next = pptps->pptps_nexthdr; 360 pptps->pptps_wptr = pptps->pptps_buffer; 361 pptps->pptps_gothdr = 0; 362 pptps->pptps_bytes = 0; 363 pptps->pptps_len = 0; 364 break; 365 } 366 } 367 368 len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen); 369 COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr); 370 pptps->pptps_bytes += len; 371 pptps->pptps_wptr += len; 372 pptps->pptps_next += len; 373 374 if (pptps->pptps_len > pptps->pptps_bytes) 375 break; 376 377 ipf_p_pptp_message(fin, nat, pptp, pptps); 378 pptps->pptps_wptr = pptps->pptps_buffer; 379 pptps->pptps_gothdr = 0; 380 pptps->pptps_bytes = 0; 381 pptps->pptps_len = 0; 382 383 start += len; 384 msg += len; 385 dlen -= len; 386 } 387 388 return (0); 389} 390 391 392/* 393 * handle a complete PPTP message 394 */ 395int 396ipf_p_pptp_message(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp, 397 pptp_side_t *pptps) 398{ 399 pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer; 400 401 switch (ntohs(hdr->pptph_type)) 402 { 403 case PPTP_MSGTYPE_CTL : 404 ipf_p_pptp_mctl(fin, nat, pptp, pptps); 405 break; 406 407 default : 408 break; 409 } 410 return (0); 411} 412 413 414/* 415 * handle a complete PPTP control message 416 */ 417int 418ipf_p_pptp_mctl(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp, 419 pptp_side_t *pptps) 420{ 421 u_short *buffer = (u_short *)(pptps->pptps_buffer); 422 pptp_side_t *pptpo; 423 424 if (pptps == &pptp->pptp_side[0]) 425 pptpo = &pptp->pptp_side[1]; 426 else 427 pptpo = &pptp->pptp_side[0]; 428 429 /* 430 * Breakout to handle all the various messages. Most are just state 431 * transition. 432 */ 433 switch (ntohs(buffer[4])) 434 { 435 case PPTP_MTCTL_STARTREQ : 436 pptps->pptps_state = PPTP_MTCTL_STARTREQ; 437 break; 438 case PPTP_MTCTL_STARTREP : 439 if (pptpo->pptps_state == PPTP_MTCTL_STARTREQ) 440 pptps->pptps_state = PPTP_MTCTL_STARTREP; 441 break; 442 case PPTP_MTCTL_STOPREQ : 443 pptps->pptps_state = PPTP_MTCTL_STOPREQ; 444 break; 445 case PPTP_MTCTL_STOPREP : 446 if (pptpo->pptps_state == PPTP_MTCTL_STOPREQ) 447 pptps->pptps_state = PPTP_MTCTL_STOPREP; 448 break; 449 case PPTP_MTCTL_ECHOREQ : 450 pptps->pptps_state = PPTP_MTCTL_ECHOREQ; 451 break; 452 case PPTP_MTCTL_ECHOREP : 453 if (pptpo->pptps_state == PPTP_MTCTL_ECHOREQ) 454 pptps->pptps_state = PPTP_MTCTL_ECHOREP; 455 break; 456 case PPTP_MTCTL_OUTREQ : 457 pptps->pptps_state = PPTP_MTCTL_OUTREQ; 458 break; 459 case PPTP_MTCTL_OUTREP : 460 if (pptpo->pptps_state == PPTP_MTCTL_OUTREQ) { 461 pptps->pptps_state = PPTP_MTCTL_OUTREP; 462 pptp->pptp_call[0] = buffer[7]; 463 pptp->pptp_call[1] = buffer[6]; 464 ipf_p_pptp_donatstate(fin, nat, pptp); 465 } 466 break; 467 case PPTP_MTCTL_INREQ : 468 pptps->pptps_state = PPTP_MTCTL_INREQ; 469 break; 470 case PPTP_MTCTL_INREP : 471 if (pptpo->pptps_state == PPTP_MTCTL_INREQ) { 472 pptps->pptps_state = PPTP_MTCTL_INREP; 473 pptp->pptp_call[0] = buffer[7]; 474 pptp->pptp_call[1] = buffer[6]; 475 ipf_p_pptp_donatstate(fin, nat, pptp); 476 } 477 break; 478 case PPTP_MTCTL_INCONNECT : 479 pptps->pptps_state = PPTP_MTCTL_INCONNECT; 480 break; 481 case PPTP_MTCTL_CLEAR : 482 pptps->pptps_state = PPTP_MTCTL_CLEAR; 483 break; 484 case PPTP_MTCTL_DISCONNECT : 485 pptps->pptps_state = PPTP_MTCTL_DISCONNECT; 486 break; 487 case PPTP_MTCTL_WANERROR : 488 pptps->pptps_state = PPTP_MTCTL_WANERROR; 489 break; 490 case PPTP_MTCTL_LINKINFO : 491 pptps->pptps_state = PPTP_MTCTL_LINKINFO; 492 break; 493 } 494 495 return (0); 496} 497 498 499/* 500 * For outgoing PPTP packets. refresh timeouts for NAT & state entries, if 501 * we can. If they have disappeared, recreate them. 502 */ 503int 504ipf_p_pptp_inout(void *arg, fr_info_t *fin, ap_session_t *aps, nat_t *nat) 505{ 506 pptp_pxy_t *pptp; 507 tcphdr_t *tcp; 508 int rev; 509 510 if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND)) 511 rev = 1; 512 else if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND)) 513 rev = 1; 514 else 515 rev = 0; 516 517 tcp = (tcphdr_t *)fin->fin_dp; 518 if ((tcp->th_flags & TH_OPENING) == TH_OPENING) { 519 pptp = (pptp_pxy_t *)aps->aps_data; 520 pptp->pptp_side[1 - rev].pptps_next = ntohl(tcp->th_ack); 521 pptp->pptp_side[1 - rev].pptps_nexthdr = ntohl(tcp->th_ack); 522 pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1; 523 pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1; 524 } 525 return (ipf_p_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data, 526 rev)); 527} 528 529 530/* 531 * clean up after ourselves. 532 */ 533void 534ipf_p_pptp_del(ipf_main_softc_t *softc, ap_session_t *aps) 535{ 536 pptp_pxy_t *pptp; 537 538 pptp = aps->aps_data; 539 540 if (pptp != NULL) { 541 /* 542 * Don't bother changing any of the NAT structure details, 543 * *_del() is on a callback from aps_free(), from nat_delete() 544 */ 545 546 READ_ENTER(&softc->ipf_state); 547 if (pptp->pptp_state != NULL) { 548 ipf_state_setpending(softc, pptp->pptp_state); 549 } 550 RWLOCK_EXIT(&softc->ipf_state); 551 552 if (pptp->pptp_nat != NULL) 553 ipf_nat_setpending(softc, pptp->pptp_nat); 554 pptp->pptp_rule->in_flags |= IPN_DELETE; 555 ipf_nat_rule_deref(softc, &pptp->pptp_rule); 556 } 557} 558