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