1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Connection tracking support for PPTP (Point to Point Tunneling Protocol). 4 * PPTP is a protocol for creating virtual private networks. 5 * It is a specification defined by Microsoft and some vendors 6 * working with Microsoft. PPTP is built on top of a modified 7 * version of the Internet Generic Routing Encapsulation Protocol. 8 * GRE is defined in RFC 1701 and RFC 1702. Documentation of 9 * PPTP can be found in RFC 2637 10 * 11 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org> 12 * 13 * Development of this code funded by Astaro AG (http://www.astaro.com/) 14 * 15 * (C) 2006-2012 Patrick McHardy <kaber@trash.net> 16 * 17 * Limitations: 18 * - We blindly assume that control connections are always 19 * established in PNS->PAC direction. This is a violation 20 * of RFC 2637 21 * - We can only support one single call within each session 22 * TODO: 23 * - testing of incoming PPTP calls 24 */ 25 26 #include <linux/module.h> 27 #include <linux/skbuff.h> 28 #include <linux/in.h> 29 #include <linux/tcp.h> 30 31 #include <net/netfilter/nf_conntrack.h> 32 #include <net/netfilter/nf_conntrack_core.h> 33 #include <net/netfilter/nf_conntrack_helper.h> 34 #include <net/netfilter/nf_conntrack_zones.h> 35 #include <linux/netfilter/nf_conntrack_proto_gre.h> 36 #include <linux/netfilter/nf_conntrack_pptp.h> 37 38 #define NF_CT_PPTP_VERSION "3.1" 39 40 MODULE_LICENSE("GPL"); 41 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 42 MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); 43 MODULE_ALIAS("ip_conntrack_pptp"); 44 MODULE_ALIAS_NFCT_HELPER("pptp"); 45 46 static DEFINE_SPINLOCK(nf_pptp_lock); 47 48 const struct nf_nat_pptp_hook __rcu *nf_nat_pptp_hook; 49 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook); 50 51 #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) 52 /* PptpControlMessageType names */ 53 static const char *const pptp_msg_name_array[PPTP_MSG_MAX + 1] = { 54 [0] = "UNKNOWN_MESSAGE", 55 [PPTP_START_SESSION_REQUEST] = "START_SESSION_REQUEST", 56 [PPTP_START_SESSION_REPLY] = "START_SESSION_REPLY", 57 [PPTP_STOP_SESSION_REQUEST] = "STOP_SESSION_REQUEST", 58 [PPTP_STOP_SESSION_REPLY] = "STOP_SESSION_REPLY", 59 [PPTP_ECHO_REQUEST] = "ECHO_REQUEST", 60 [PPTP_ECHO_REPLY] = "ECHO_REPLY", 61 [PPTP_OUT_CALL_REQUEST] = "OUT_CALL_REQUEST", 62 [PPTP_OUT_CALL_REPLY] = "OUT_CALL_REPLY", 63 [PPTP_IN_CALL_REQUEST] = "IN_CALL_REQUEST", 64 [PPTP_IN_CALL_REPLY] = "IN_CALL_REPLY", 65 [PPTP_IN_CALL_CONNECT] = "IN_CALL_CONNECT", 66 [PPTP_CALL_CLEAR_REQUEST] = "CALL_CLEAR_REQUEST", 67 [PPTP_CALL_DISCONNECT_NOTIFY] = "CALL_DISCONNECT_NOTIFY", 68 [PPTP_WAN_ERROR_NOTIFY] = "WAN_ERROR_NOTIFY", 69 [PPTP_SET_LINK_INFO] = "SET_LINK_INFO" 70 }; 71 72 const char *pptp_msg_name(u_int16_t msg) 73 { 74 if (msg > PPTP_MSG_MAX) 75 return pptp_msg_name_array[0]; 76 77 return pptp_msg_name_array[msg]; 78 } 79 EXPORT_SYMBOL(pptp_msg_name); 80 #endif 81 82 #define SECS *HZ 83 #define MINS * 60 SECS 84 #define HOURS * 60 MINS 85 86 #define PPTP_GRE_TIMEOUT (10 MINS) 87 #define PPTP_GRE_STREAM_TIMEOUT (5 HOURS) 88 89 static void pptp_expectfn(struct nf_conn *ct, 90 struct nf_conntrack_expect *exp) 91 { 92 const struct nf_nat_pptp_hook *hook; 93 struct net *net = nf_ct_net(ct); 94 pr_debug("increasing timeouts\n"); 95 96 /* increase timeout of GRE data channel conntrack entry */ 97 ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; 98 ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT; 99 100 /* Can you see how rusty this code is, compared with the pre-2.6.11 101 * one? That's what happened to my shiny newnat of 2002 ;( -HW */ 102 103 hook = rcu_dereference(nf_nat_pptp_hook); 104 if (hook && ct->master->status & IPS_NAT_MASK) 105 hook->expectfn(ct, exp); 106 else { 107 struct nf_conntrack_tuple inv_t; 108 struct nf_conntrack_expect *exp_other; 109 110 /* obviously this tuple inversion only works until you do NAT */ 111 nf_ct_invert_tuple(&inv_t, &exp->tuple); 112 pr_debug("trying to unexpect other dir: "); 113 nf_ct_dump_tuple(&inv_t); 114 115 exp_other = nf_ct_expect_find_get(net, nf_ct_zone(ct), &inv_t); 116 if (exp_other) { 117 /* delete other expectation. */ 118 pr_debug("found\n"); 119 nf_ct_unexpect_related(exp_other); 120 nf_ct_expect_put(exp_other); 121 } else { 122 pr_debug("not found\n"); 123 } 124 } 125 } 126 127 /* expect GRE connections (PNS->PAC and PAC->PNS direction) */ 128 static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid) 129 { 130 struct nf_conntrack_expect *exp_orig, *exp_reply; 131 const struct nf_nat_pptp_hook *hook; 132 enum ip_conntrack_dir dir; 133 int ret = 1; 134 135 exp_orig = nf_ct_expect_alloc(ct); 136 if (exp_orig == NULL) 137 goto out; 138 139 exp_reply = nf_ct_expect_alloc(ct); 140 if (exp_reply == NULL) 141 goto out_put_orig; 142 143 /* original direction, PNS->PAC */ 144 dir = IP_CT_DIR_ORIGINAL; 145 nf_ct_expect_init(exp_orig, NF_CT_EXPECT_CLASS_DEFAULT, 146 nf_ct_l3num(ct), 147 &ct->tuplehash[dir].tuple.src.u3, 148 &ct->tuplehash[dir].tuple.dst.u3, 149 IPPROTO_GRE, &peer_callid, &callid); 150 exp_orig->expectfn = pptp_expectfn; 151 152 /* reply direction, PAC->PNS */ 153 dir = IP_CT_DIR_REPLY; 154 nf_ct_expect_init(exp_reply, NF_CT_EXPECT_CLASS_DEFAULT, 155 nf_ct_l3num(ct), 156 &ct->tuplehash[dir].tuple.src.u3, 157 &ct->tuplehash[dir].tuple.dst.u3, 158 IPPROTO_GRE, &callid, &peer_callid); 159 exp_reply->expectfn = pptp_expectfn; 160 161 hook = rcu_dereference(nf_nat_pptp_hook); 162 if (hook && ct->status & IPS_NAT_MASK) 163 hook->exp_gre(exp_orig, exp_reply); 164 if (nf_ct_expect_related(exp_orig, 0) != 0) 165 goto out_put_both; 166 if (nf_ct_expect_related(exp_reply, 0) != 0) 167 goto out_unexpect_orig; 168 169 if (!nf_ct_gre_keymap_add(ct, &exp_orig->tuple, 170 &exp_reply->tuple)) 171 goto out_unexpect_both; 172 ret = 0; 173 174 out_put_both: 175 nf_ct_expect_put(exp_reply); 176 out_put_orig: 177 nf_ct_expect_put(exp_orig); 178 out: 179 return ret; 180 181 out_unexpect_both: 182 nf_ct_unexpect_related(exp_reply); 183 out_unexpect_orig: 184 nf_ct_unexpect_related(exp_orig); 185 goto out_put_both; 186 } 187 188 static int 189 pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, 190 struct PptpControlHeader *ctlh, 191 union pptp_ctrl_union *pptpReq, 192 unsigned int reqlen, 193 struct nf_conn *ct, 194 enum ip_conntrack_info ctinfo) 195 { 196 struct nf_ct_pptp_master *info = nfct_help_data(ct); 197 const struct nf_nat_pptp_hook *hook; 198 u_int16_t msg; 199 __be16 cid = 0, pcid = 0; 200 201 if (!info) 202 return NF_DROP; 203 204 msg = ntohs(ctlh->messageType); 205 pr_debug("inbound control message %s\n", pptp_msg_name(msg)); 206 207 switch (msg) { 208 case PPTP_START_SESSION_REPLY: 209 /* server confirms new control session */ 210 if (info->sstate < PPTP_SESSION_REQUESTED) 211 goto invalid; 212 if (pptpReq->srep.resultCode == PPTP_START_OK) 213 info->sstate = PPTP_SESSION_CONFIRMED; 214 else 215 info->sstate = PPTP_SESSION_ERROR; 216 break; 217 218 case PPTP_STOP_SESSION_REPLY: 219 /* server confirms end of control session */ 220 if (info->sstate > PPTP_SESSION_STOPREQ) 221 goto invalid; 222 if (pptpReq->strep.resultCode == PPTP_STOP_OK) 223 info->sstate = PPTP_SESSION_NONE; 224 else 225 info->sstate = PPTP_SESSION_ERROR; 226 break; 227 228 case PPTP_OUT_CALL_REPLY: 229 /* server accepted call, we now expect GRE frames */ 230 if (info->sstate != PPTP_SESSION_CONFIRMED) 231 goto invalid; 232 if (info->cstate != PPTP_CALL_OUT_REQ && 233 info->cstate != PPTP_CALL_OUT_CONF) 234 goto invalid; 235 236 cid = pptpReq->ocack.callID; 237 pcid = pptpReq->ocack.peersCallID; 238 if (info->pns_call_id != pcid) 239 goto invalid; 240 pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name(msg), 241 ntohs(cid), ntohs(pcid)); 242 243 if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) { 244 info->cstate = PPTP_CALL_OUT_CONF; 245 info->pac_call_id = cid; 246 exp_gre(ct, cid, pcid); 247 } else 248 info->cstate = PPTP_CALL_NONE; 249 break; 250 251 case PPTP_IN_CALL_REQUEST: 252 /* server tells us about incoming call request */ 253 if (info->sstate != PPTP_SESSION_CONFIRMED) 254 goto invalid; 255 256 cid = pptpReq->icreq.callID; 257 pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid)); 258 info->cstate = PPTP_CALL_IN_REQ; 259 info->pac_call_id = cid; 260 break; 261 262 case PPTP_IN_CALL_CONNECT: 263 /* server tells us about incoming call established */ 264 if (info->sstate != PPTP_SESSION_CONFIRMED) 265 goto invalid; 266 if (info->cstate != PPTP_CALL_IN_REP && 267 info->cstate != PPTP_CALL_IN_CONF) 268 goto invalid; 269 270 pcid = pptpReq->iccon.peersCallID; 271 cid = info->pac_call_id; 272 273 if (info->pns_call_id != pcid) 274 goto invalid; 275 276 pr_debug("%s, PCID=%X\n", pptp_msg_name(msg), ntohs(pcid)); 277 info->cstate = PPTP_CALL_IN_CONF; 278 279 /* we expect a GRE connection from PAC to PNS */ 280 exp_gre(ct, cid, pcid); 281 break; 282 283 case PPTP_CALL_DISCONNECT_NOTIFY: 284 /* server confirms disconnect */ 285 cid = pptpReq->disc.callID; 286 pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid)); 287 info->cstate = PPTP_CALL_NONE; 288 289 /* untrack this call id, unexpect GRE packets */ 290 gre_pptp_destroy_siblings(ct); 291 break; 292 293 case PPTP_WAN_ERROR_NOTIFY: 294 case PPTP_SET_LINK_INFO: 295 case PPTP_ECHO_REQUEST: 296 case PPTP_ECHO_REPLY: 297 /* I don't have to explain these ;) */ 298 break; 299 300 default: 301 goto invalid; 302 } 303 304 hook = rcu_dereference(nf_nat_pptp_hook); 305 if (hook && ct->status & IPS_NAT_MASK) 306 return hook->inbound(skb, ct, ctinfo, protoff, ctlh, pptpReq); 307 return NF_ACCEPT; 308 309 invalid: 310 pr_debug("invalid %s: type=%d cid=%u pcid=%u " 311 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", 312 pptp_msg_name(msg), 313 msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, 314 ntohs(info->pns_call_id), ntohs(info->pac_call_id)); 315 return NF_ACCEPT; 316 } 317 318 static int 319 pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff, 320 struct PptpControlHeader *ctlh, 321 union pptp_ctrl_union *pptpReq, 322 unsigned int reqlen, 323 struct nf_conn *ct, 324 enum ip_conntrack_info ctinfo) 325 { 326 struct nf_ct_pptp_master *info = nfct_help_data(ct); 327 const struct nf_nat_pptp_hook *hook; 328 u_int16_t msg; 329 __be16 cid = 0, pcid = 0; 330 331 if (!info) 332 return NF_DROP; 333 334 msg = ntohs(ctlh->messageType); 335 pr_debug("outbound control message %s\n", pptp_msg_name(msg)); 336 337 switch (msg) { 338 case PPTP_START_SESSION_REQUEST: 339 /* client requests for new control session */ 340 if (info->sstate != PPTP_SESSION_NONE) 341 goto invalid; 342 info->sstate = PPTP_SESSION_REQUESTED; 343 break; 344 345 case PPTP_STOP_SESSION_REQUEST: 346 /* client requests end of control session */ 347 info->sstate = PPTP_SESSION_STOPREQ; 348 break; 349 350 case PPTP_OUT_CALL_REQUEST: 351 /* client initiating connection to server */ 352 if (info->sstate != PPTP_SESSION_CONFIRMED) 353 goto invalid; 354 info->cstate = PPTP_CALL_OUT_REQ; 355 /* track PNS call id */ 356 cid = pptpReq->ocreq.callID; 357 pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid)); 358 info->pns_call_id = cid; 359 break; 360 361 case PPTP_IN_CALL_REPLY: 362 /* client answers incoming call */ 363 if (info->cstate != PPTP_CALL_IN_REQ && 364 info->cstate != PPTP_CALL_IN_REP) 365 goto invalid; 366 367 cid = pptpReq->icack.callID; 368 pcid = pptpReq->icack.peersCallID; 369 if (info->pac_call_id != pcid) 370 goto invalid; 371 pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name(msg), 372 ntohs(cid), ntohs(pcid)); 373 374 if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) { 375 /* part two of the three-way handshake */ 376 info->cstate = PPTP_CALL_IN_REP; 377 info->pns_call_id = cid; 378 } else 379 info->cstate = PPTP_CALL_NONE; 380 break; 381 382 case PPTP_CALL_CLEAR_REQUEST: 383 /* client requests hangup of call */ 384 if (info->sstate != PPTP_SESSION_CONFIRMED) 385 goto invalid; 386 /* FUTURE: iterate over all calls and check if 387 * call ID is valid. We don't do this without newnat, 388 * because we only know about last call */ 389 info->cstate = PPTP_CALL_CLEAR_REQ; 390 break; 391 392 case PPTP_SET_LINK_INFO: 393 case PPTP_ECHO_REQUEST: 394 case PPTP_ECHO_REPLY: 395 /* I don't have to explain these ;) */ 396 break; 397 398 default: 399 goto invalid; 400 } 401 402 hook = rcu_dereference(nf_nat_pptp_hook); 403 if (hook && ct->status & IPS_NAT_MASK) 404 return hook->outbound(skb, ct, ctinfo, protoff, ctlh, pptpReq); 405 return NF_ACCEPT; 406 407 invalid: 408 pr_debug("invalid %s: type=%d cid=%u pcid=%u " 409 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", 410 pptp_msg_name(msg), 411 msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, 412 ntohs(info->pns_call_id), ntohs(info->pac_call_id)); 413 return NF_ACCEPT; 414 } 415 416 static const unsigned int pptp_msg_size[] = { 417 [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest), 418 [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply), 419 [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest), 420 [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply), 421 [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest), 422 [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply), 423 [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest), 424 [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply), 425 [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected), 426 [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest), 427 [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify), 428 [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify), 429 [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo), 430 }; 431 432 /* track caller id inside control connection, call expect_related */ 433 static int 434 conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, 435 struct nf_conn *ct, enum ip_conntrack_info ctinfo) 436 437 { 438 int dir = CTINFO2DIR(ctinfo); 439 const struct nf_ct_pptp_master *info = nfct_help_data(ct); 440 const struct tcphdr *tcph; 441 struct tcphdr _tcph; 442 const struct pptp_pkt_hdr *pptph; 443 struct pptp_pkt_hdr _pptph; 444 struct PptpControlHeader _ctlh, *ctlh; 445 union pptp_ctrl_union _pptpReq, *pptpReq; 446 unsigned int tcplen = skb->len - protoff; 447 unsigned int datalen, reqlen, nexthdr_off; 448 int oldsstate, oldcstate; 449 int ret; 450 u_int16_t msg; 451 452 if (!info) 453 return NF_DROP; 454 455 #if IS_ENABLED(CONFIG_NF_NAT) 456 if (!nf_ct_is_confirmed(ct) && (ct->status & IPS_NAT_MASK)) { 457 struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); 458 459 if (!nat && !nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC)) 460 return NF_DROP; 461 } 462 #endif 463 /* don't do any tracking before tcp handshake complete */ 464 if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) 465 return NF_ACCEPT; 466 467 nexthdr_off = protoff; 468 tcph = skb_header_pointer(skb, nexthdr_off, sizeof(_tcph), &_tcph); 469 if (!tcph) 470 return NF_ACCEPT; 471 472 nexthdr_off += tcph->doff * 4; 473 datalen = tcplen - tcph->doff * 4; 474 475 pptph = skb_header_pointer(skb, nexthdr_off, sizeof(_pptph), &_pptph); 476 if (!pptph) { 477 pr_debug("no full PPTP header, can't track\n"); 478 return NF_ACCEPT; 479 } 480 nexthdr_off += sizeof(_pptph); 481 datalen -= sizeof(_pptph); 482 483 /* if it's not a control message we can't do anything with it */ 484 if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || 485 ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { 486 pr_debug("not a control packet\n"); 487 return NF_ACCEPT; 488 } 489 490 ctlh = skb_header_pointer(skb, nexthdr_off, sizeof(_ctlh), &_ctlh); 491 if (!ctlh) 492 return NF_ACCEPT; 493 nexthdr_off += sizeof(_ctlh); 494 datalen -= sizeof(_ctlh); 495 496 reqlen = datalen; 497 msg = ntohs(ctlh->messageType); 498 if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg]) 499 return NF_ACCEPT; 500 if (reqlen > sizeof(*pptpReq)) 501 reqlen = sizeof(*pptpReq); 502 503 pptpReq = skb_header_pointer(skb, nexthdr_off, reqlen, &_pptpReq); 504 if (!pptpReq) 505 return NF_ACCEPT; 506 507 oldsstate = info->sstate; 508 oldcstate = info->cstate; 509 510 spin_lock_bh(&nf_pptp_lock); 511 512 /* FIXME: We just blindly assume that the control connection is always 513 * established from PNS->PAC. However, RFC makes no guarantee */ 514 if (dir == IP_CT_DIR_ORIGINAL) 515 /* client -> server (PNS -> PAC) */ 516 ret = pptp_outbound_pkt(skb, protoff, ctlh, pptpReq, reqlen, ct, 517 ctinfo); 518 else 519 /* server -> client (PAC -> PNS) */ 520 ret = pptp_inbound_pkt(skb, protoff, ctlh, pptpReq, reqlen, ct, 521 ctinfo); 522 pr_debug("sstate: %d->%d, cstate: %d->%d\n", 523 oldsstate, info->sstate, oldcstate, info->cstate); 524 spin_unlock_bh(&nf_pptp_lock); 525 526 return ret; 527 } 528 529 static const struct nf_conntrack_expect_policy pptp_exp_policy = { 530 .max_expected = 2, 531 .timeout = 5 * 60, 532 }; 533 534 /* control protocol helper */ 535 static struct nf_conntrack_helper pptp __read_mostly; 536 static struct nf_conntrack_helper *pptp_ptr __read_mostly; 537 538 static int __init nf_conntrack_pptp_init(void) 539 { 540 NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_pptp_master)); 541 542 nf_ct_helper_init(&pptp, AF_INET, IPPROTO_TCP, 543 "pptp", PPTP_CONTROL_PORT, PPTP_CONTROL_PORT, PPTP_CONTROL_PORT, 544 &pptp_exp_policy, 0, conntrack_pptp_help, NULL, THIS_MODULE); 545 546 pptp.destroy = gre_pptp_destroy_siblings; 547 548 nf_conntrack_helper_deprecated(pptp.name); 549 550 return nf_conntrack_helper_register(&pptp, &pptp_ptr); 551 } 552 553 static void __exit nf_conntrack_pptp_fini(void) 554 { 555 nf_conntrack_helper_unregister(pptp_ptr); 556 } 557 558 module_init(nf_conntrack_pptp_init); 559 module_exit(nf_conntrack_pptp_fini); 560