diff options
author | Patrick McHardy <kaber@trash.net> | 2006-09-20 15:10:21 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:20:16 -0400 |
commit | 87a0117afdfe64473a6c802501bc15aee145ebb8 (patch) | |
tree | 7c31d2ade86cc3de46a9256aaf707d7a838df79a /net/ipv4 | |
parent | 4c651756d502e72a68b0bc6fb20bb18c68785227 (diff) |
[NETFILTER]: PPTP conntrack: clean up debugging cruft
Also make sure not to hand packets received in an invalid state to the
NAT helper since it will mangle the packet with invalid data.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_helper_pptp.c | 128 |
1 files changed, 51 insertions, 77 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index 9a98a6ce1901..7b6d5aaca4da 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c | |||
@@ -301,7 +301,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
301 | { | 301 | { |
302 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; | 302 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; |
303 | u_int16_t msg; | 303 | u_int16_t msg; |
304 | __be16 cid, pcid; | 304 | __be16 cid = 0, pcid = 0; |
305 | 305 | ||
306 | msg = ntohs(ctlh->messageType); | 306 | msg = ntohs(ctlh->messageType); |
307 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); | 307 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); |
@@ -309,11 +309,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
309 | switch (msg) { | 309 | switch (msg) { |
310 | case PPTP_START_SESSION_REPLY: | 310 | case PPTP_START_SESSION_REPLY: |
311 | /* server confirms new control session */ | 311 | /* server confirms new control session */ |
312 | if (info->sstate < PPTP_SESSION_REQUESTED) { | 312 | if (info->sstate < PPTP_SESSION_REQUESTED) |
313 | DEBUGP("%s without START_SESS_REQUEST\n", | 313 | goto invalid; |
314 | pptp_msg_name[msg]); | ||
315 | break; | ||
316 | } | ||
317 | if (pptpReq->srep.resultCode == PPTP_START_OK) | 314 | if (pptpReq->srep.resultCode == PPTP_START_OK) |
318 | info->sstate = PPTP_SESSION_CONFIRMED; | 315 | info->sstate = PPTP_SESSION_CONFIRMED; |
319 | else | 316 | else |
@@ -322,11 +319,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
322 | 319 | ||
323 | case PPTP_STOP_SESSION_REPLY: | 320 | case PPTP_STOP_SESSION_REPLY: |
324 | /* server confirms end of control session */ | 321 | /* server confirms end of control session */ |
325 | if (info->sstate > PPTP_SESSION_STOPREQ) { | 322 | if (info->sstate > PPTP_SESSION_STOPREQ) |
326 | DEBUGP("%s without STOP_SESS_REQUEST\n", | 323 | goto invalid; |
327 | pptp_msg_name[msg]); | ||
328 | break; | ||
329 | } | ||
330 | if (pptpReq->strep.resultCode == PPTP_STOP_OK) | 324 | if (pptpReq->strep.resultCode == PPTP_STOP_OK) |
331 | info->sstate = PPTP_SESSION_NONE; | 325 | info->sstate = PPTP_SESSION_NONE; |
332 | else | 326 | else |
@@ -335,15 +329,12 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
335 | 329 | ||
336 | case PPTP_OUT_CALL_REPLY: | 330 | case PPTP_OUT_CALL_REPLY: |
337 | /* server accepted call, we now expect GRE frames */ | 331 | /* server accepted call, we now expect GRE frames */ |
338 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 332 | if (info->sstate != PPTP_SESSION_CONFIRMED) |
339 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | 333 | goto invalid; |
340 | break; | ||
341 | } | ||
342 | if (info->cstate != PPTP_CALL_OUT_REQ && | 334 | if (info->cstate != PPTP_CALL_OUT_REQ && |
343 | info->cstate != PPTP_CALL_OUT_CONF) { | 335 | info->cstate != PPTP_CALL_OUT_CONF) |
344 | DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]); | 336 | goto invalid; |
345 | break; | 337 | |
346 | } | ||
347 | if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) { | 338 | if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) { |
348 | info->cstate = PPTP_CALL_NONE; | 339 | info->cstate = PPTP_CALL_NONE; |
349 | break; | 340 | break; |
@@ -354,11 +345,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
354 | 345 | ||
355 | info->pac_call_id = cid; | 346 | info->pac_call_id = cid; |
356 | 347 | ||
357 | if (info->pns_call_id != pcid) { | 348 | if (info->pns_call_id != pcid) |
358 | DEBUGP("%s for unknown callid %u\n", | 349 | goto invalid; |
359 | pptp_msg_name[msg], ntohs(pcid)); | ||
360 | break; | ||
361 | } | ||
362 | 350 | ||
363 | DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], | 351 | DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], |
364 | ntohs(cid), ntohs(pcid)); | 352 | ntohs(cid), ntohs(pcid)); |
@@ -370,10 +358,9 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
370 | 358 | ||
371 | case PPTP_IN_CALL_REQUEST: | 359 | case PPTP_IN_CALL_REQUEST: |
372 | /* server tells us about incoming call request */ | 360 | /* server tells us about incoming call request */ |
373 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 361 | if (info->sstate != PPTP_SESSION_CONFIRMED) |
374 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | 362 | goto invalid; |
375 | break; | 363 | |
376 | } | ||
377 | pcid = pptpReq->icack.peersCallID; | 364 | pcid = pptpReq->icack.peersCallID; |
378 | DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); | 365 | DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); |
379 | info->cstate = PPTP_CALL_IN_REQ; | 366 | info->cstate = PPTP_CALL_IN_REQ; |
@@ -382,25 +369,17 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
382 | 369 | ||
383 | case PPTP_IN_CALL_CONNECT: | 370 | case PPTP_IN_CALL_CONNECT: |
384 | /* server tells us about incoming call established */ | 371 | /* server tells us about incoming call established */ |
385 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 372 | if (info->sstate != PPTP_SESSION_CONFIRMED) |
386 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | 373 | goto invalid; |
387 | break; | 374 | if (info->cstate != PPTP_CALL_IN_REP && |
388 | } | 375 | info->cstate != PPTP_CALL_IN_CONF) |
389 | if (info->cstate != PPTP_CALL_IN_REP | 376 | goto invalid; |
390 | && info->cstate != PPTP_CALL_IN_CONF) { | ||
391 | DEBUGP("%s but never sent IN_CALL_REPLY\n", | ||
392 | pptp_msg_name[msg]); | ||
393 | break; | ||
394 | } | ||
395 | 377 | ||
396 | pcid = pptpReq->iccon.peersCallID; | 378 | pcid = pptpReq->iccon.peersCallID; |
397 | cid = info->pac_call_id; | 379 | cid = info->pac_call_id; |
398 | 380 | ||
399 | if (info->pns_call_id != pcid) { | 381 | if (info->pns_call_id != pcid) |
400 | DEBUGP("%s for unknown CallID %u\n", | 382 | goto invalid; |
401 | pptp_msg_name[msg], ntohs(pcid)); | ||
402 | break; | ||
403 | } | ||
404 | 383 | ||
405 | DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); | 384 | DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); |
406 | info->cstate = PPTP_CALL_IN_CONF; | 385 | info->cstate = PPTP_CALL_IN_CONF; |
@@ -425,18 +404,21 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
425 | /* I don't have to explain these ;) */ | 404 | /* I don't have to explain these ;) */ |
426 | break; | 405 | break; |
427 | default: | 406 | default: |
428 | DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX) | 407 | goto invalid; |
429 | ? pptp_msg_name[msg]:pptp_msg_name[0], msg); | ||
430 | break; | ||
431 | } | 408 | } |
432 | 409 | ||
433 | |||
434 | if (ip_nat_pptp_hook_inbound) | 410 | if (ip_nat_pptp_hook_inbound) |
435 | return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, | 411 | return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, |
436 | pptpReq); | 412 | pptpReq); |
437 | |||
438 | return NF_ACCEPT; | 413 | return NF_ACCEPT; |
439 | 414 | ||
415 | invalid: | ||
416 | DEBUGP("invalid %s: type=%d cid=%u pcid=%u " | ||
417 | "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", | ||
418 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], | ||
419 | msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, | ||
420 | ntohs(info->pns_call_id), ntohs(info->pac_call_id)); | ||
421 | return NF_ACCEPT; | ||
440 | } | 422 | } |
441 | 423 | ||
442 | static inline int | 424 | static inline int |
@@ -449,7 +431,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
449 | { | 431 | { |
450 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; | 432 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; |
451 | u_int16_t msg; | 433 | u_int16_t msg; |
452 | __be16 cid, pcid; | 434 | __be16 cid = 0, pcid = 0; |
453 | 435 | ||
454 | msg = ntohs(ctlh->messageType); | 436 | msg = ntohs(ctlh->messageType); |
455 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); | 437 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); |
@@ -457,10 +439,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
457 | switch (msg) { | 439 | switch (msg) { |
458 | case PPTP_START_SESSION_REQUEST: | 440 | case PPTP_START_SESSION_REQUEST: |
459 | /* client requests for new control session */ | 441 | /* client requests for new control session */ |
460 | if (info->sstate != PPTP_SESSION_NONE) { | 442 | if (info->sstate != PPTP_SESSION_NONE) |
461 | DEBUGP("%s but we already have one", | 443 | goto invalid; |
462 | pptp_msg_name[msg]); | ||
463 | } | ||
464 | info->sstate = PPTP_SESSION_REQUESTED; | 444 | info->sstate = PPTP_SESSION_REQUESTED; |
465 | break; | 445 | break; |
466 | case PPTP_STOP_SESSION_REQUEST: | 446 | case PPTP_STOP_SESSION_REQUEST: |
@@ -470,11 +450,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
470 | 450 | ||
471 | case PPTP_OUT_CALL_REQUEST: | 451 | case PPTP_OUT_CALL_REQUEST: |
472 | /* client initiating connection to server */ | 452 | /* client initiating connection to server */ |
473 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 453 | if (info->sstate != PPTP_SESSION_CONFIRMED) |
474 | DEBUGP("%s but no session\n", | 454 | goto invalid; |
475 | pptp_msg_name[msg]); | ||
476 | break; | ||
477 | } | ||
478 | info->cstate = PPTP_CALL_OUT_REQ; | 455 | info->cstate = PPTP_CALL_OUT_REQ; |
479 | /* track PNS call id */ | 456 | /* track PNS call id */ |
480 | cid = pptpReq->ocreq.callID; | 457 | cid = pptpReq->ocreq.callID; |
@@ -483,22 +460,17 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
483 | break; | 460 | break; |
484 | case PPTP_IN_CALL_REPLY: | 461 | case PPTP_IN_CALL_REPLY: |
485 | /* client answers incoming call */ | 462 | /* client answers incoming call */ |
486 | if (info->cstate != PPTP_CALL_IN_REQ | 463 | if (info->cstate != PPTP_CALL_IN_REQ && |
487 | && info->cstate != PPTP_CALL_IN_REP) { | 464 | info->cstate != PPTP_CALL_IN_REP) |
488 | DEBUGP("%s without incall_req\n", | 465 | goto invalid; |
489 | pptp_msg_name[msg]); | 466 | |
490 | break; | ||
491 | } | ||
492 | if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) { | 467 | if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) { |
493 | info->cstate = PPTP_CALL_NONE; | 468 | info->cstate = PPTP_CALL_NONE; |
494 | break; | 469 | break; |
495 | } | 470 | } |
496 | pcid = pptpReq->icack.peersCallID; | 471 | pcid = pptpReq->icack.peersCallID; |
497 | if (info->pac_call_id != pcid) { | 472 | if (info->pac_call_id != pcid) |
498 | DEBUGP("%s for unknown call %u\n", | 473 | goto invalid; |
499 | pptp_msg_name[msg], ntohs(pcid)); | ||
500 | break; | ||
501 | } | ||
502 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(pcid)); | 474 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(pcid)); |
503 | /* part two of the three-way handshake */ | 475 | /* part two of the three-way handshake */ |
504 | info->cstate = PPTP_CALL_IN_REP; | 476 | info->cstate = PPTP_CALL_IN_REP; |
@@ -507,10 +479,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
507 | 479 | ||
508 | case PPTP_CALL_CLEAR_REQUEST: | 480 | case PPTP_CALL_CLEAR_REQUEST: |
509 | /* client requests hangup of call */ | 481 | /* client requests hangup of call */ |
510 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 482 | if (info->sstate != PPTP_SESSION_CONFIRMED) |
511 | DEBUGP("CLEAR_CALL but no session\n"); | 483 | goto invalid; |
512 | break; | ||
513 | } | ||
514 | /* FUTURE: iterate over all calls and check if | 484 | /* FUTURE: iterate over all calls and check if |
515 | * call ID is valid. We don't do this without newnat, | 485 | * call ID is valid. We don't do this without newnat, |
516 | * because we only know about last call */ | 486 | * because we only know about last call */ |
@@ -522,16 +492,20 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
522 | /* I don't have to explain these ;) */ | 492 | /* I don't have to explain these ;) */ |
523 | break; | 493 | break; |
524 | default: | 494 | default: |
525 | DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? | 495 | goto invalid; |
526 | pptp_msg_name[msg]:pptp_msg_name[0], msg); | ||
527 | /* unknown: no need to create GRE masq table entry */ | ||
528 | break; | ||
529 | } | 496 | } |
530 | 497 | ||
531 | if (ip_nat_pptp_hook_outbound) | 498 | if (ip_nat_pptp_hook_outbound) |
532 | return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, | 499 | return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, |
533 | pptpReq); | 500 | pptpReq); |
501 | return NF_ACCEPT; | ||
534 | 502 | ||
503 | invalid: | ||
504 | DEBUGP("invalid %s: type=%d cid=%u pcid=%u " | ||
505 | "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", | ||
506 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], | ||
507 | msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, | ||
508 | ntohs(info->pns_call_id), ntohs(info->pac_call_id)); | ||
535 | return NF_ACCEPT; | 509 | return NF_ACCEPT; |
536 | } | 510 | } |
537 | 511 | ||