diff options
author | Patrick McHardy <kaber@trash.net> | 2006-09-20 15:09:51 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:20:14 -0400 |
commit | a1073406a124c1d3b33a0f06bfb8078a9ddd1985 (patch) | |
tree | f00172adc188074a998d39df64f258c1048d6f73 /net | |
parent | cf9f81523ef3e95d9f222c896d266e4562999150 (diff) |
[NETFILTER]: PPTP conntrack: consolidate header size checks
Also make sure not to pass undersized messages to the NAT helper.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_helper_pptp.c | 65 |
1 files changed, 22 insertions, 43 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index 57eac6e3871a..3b5464fa4217 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c | |||
@@ -291,6 +291,22 @@ out_unexpect_orig: | |||
291 | goto out_put_both; | 291 | goto out_put_both; |
292 | } | 292 | } |
293 | 293 | ||
294 | static const unsigned int pptp_msg_size[] = { | ||
295 | [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest), | ||
296 | [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply), | ||
297 | [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest), | ||
298 | [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply), | ||
299 | [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest), | ||
300 | [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply), | ||
301 | [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest), | ||
302 | [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply), | ||
303 | [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected), | ||
304 | [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest), | ||
305 | [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify), | ||
306 | [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify), | ||
307 | [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo), | ||
308 | }; | ||
309 | |||
294 | static inline int | 310 | static inline int |
295 | pptp_inbound_pkt(struct sk_buff **pskb, | 311 | pptp_inbound_pkt(struct sk_buff **pskb, |
296 | struct tcphdr *tcph, | 312 | struct tcphdr *tcph, |
@@ -326,13 +342,11 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
326 | msg = ntohs(ctlh->messageType); | 342 | msg = ntohs(ctlh->messageType); |
327 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); | 343 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); |
328 | 344 | ||
345 | if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg]) | ||
346 | return NF_ACCEPT; | ||
347 | |||
329 | switch (msg) { | 348 | switch (msg) { |
330 | case PPTP_START_SESSION_REPLY: | 349 | case PPTP_START_SESSION_REPLY: |
331 | if (reqlen < sizeof(_pptpReq.srep)) { | ||
332 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | /* server confirms new control session */ | 350 | /* server confirms new control session */ |
337 | if (info->sstate < PPTP_SESSION_REQUESTED) { | 351 | if (info->sstate < PPTP_SESSION_REQUESTED) { |
338 | DEBUGP("%s without START_SESS_REQUEST\n", | 352 | DEBUGP("%s without START_SESS_REQUEST\n", |
@@ -346,11 +360,6 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
346 | break; | 360 | break; |
347 | 361 | ||
348 | case PPTP_STOP_SESSION_REPLY: | 362 | case PPTP_STOP_SESSION_REPLY: |
349 | if (reqlen < sizeof(_pptpReq.strep)) { | ||
350 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | /* server confirms end of control session */ | 363 | /* server confirms end of control session */ |
355 | if (info->sstate > PPTP_SESSION_STOPREQ) { | 364 | if (info->sstate > PPTP_SESSION_STOPREQ) { |
356 | DEBUGP("%s without STOP_SESS_REQUEST\n", | 365 | DEBUGP("%s without STOP_SESS_REQUEST\n", |
@@ -364,11 +373,6 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
364 | break; | 373 | break; |
365 | 374 | ||
366 | case PPTP_OUT_CALL_REPLY: | 375 | case PPTP_OUT_CALL_REPLY: |
367 | if (reqlen < sizeof(_pptpReq.ocack)) { | ||
368 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | /* server accepted call, we now expect GRE frames */ | 376 | /* server accepted call, we now expect GRE frames */ |
373 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 377 | if (info->sstate != PPTP_SESSION_CONFIRMED) { |
374 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | 378 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); |
@@ -404,11 +408,6 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
404 | break; | 408 | break; |
405 | 409 | ||
406 | case PPTP_IN_CALL_REQUEST: | 410 | case PPTP_IN_CALL_REQUEST: |
407 | if (reqlen < sizeof(_pptpReq.icack)) { | ||
408 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
409 | break; | ||
410 | } | ||
411 | |||
412 | /* server tells us about incoming call request */ | 411 | /* server tells us about incoming call request */ |
413 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 412 | if (info->sstate != PPTP_SESSION_CONFIRMED) { |
414 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | 413 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); |
@@ -421,11 +420,6 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
421 | break; | 420 | break; |
422 | 421 | ||
423 | case PPTP_IN_CALL_CONNECT: | 422 | case PPTP_IN_CALL_CONNECT: |
424 | if (reqlen < sizeof(_pptpReq.iccon)) { | ||
425 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
426 | break; | ||
427 | } | ||
428 | |||
429 | /* server tells us about incoming call established */ | 423 | /* server tells us about incoming call established */ |
430 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 424 | if (info->sstate != PPTP_SESSION_CONFIRMED) { |
431 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | 425 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); |
@@ -455,11 +449,6 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
455 | break; | 449 | break; |
456 | 450 | ||
457 | case PPTP_CALL_DISCONNECT_NOTIFY: | 451 | case PPTP_CALL_DISCONNECT_NOTIFY: |
458 | if (reqlen < sizeof(_pptpReq.disc)) { | ||
459 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
460 | break; | ||
461 | } | ||
462 | |||
463 | /* server confirms disconnect */ | 452 | /* server confirms disconnect */ |
464 | cid = pptpReq->disc.callID; | 453 | cid = pptpReq->disc.callID; |
465 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); | 454 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); |
@@ -470,8 +459,6 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
470 | break; | 459 | break; |
471 | 460 | ||
472 | case PPTP_WAN_ERROR_NOTIFY: | 461 | case PPTP_WAN_ERROR_NOTIFY: |
473 | break; | ||
474 | |||
475 | case PPTP_ECHO_REQUEST: | 462 | case PPTP_ECHO_REQUEST: |
476 | case PPTP_ECHO_REPLY: | 463 | case PPTP_ECHO_REPLY: |
477 | /* I don't have to explain these ;) */ | 464 | /* I don't have to explain these ;) */ |
@@ -522,6 +509,9 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
522 | msg = ntohs(ctlh->messageType); | 509 | msg = ntohs(ctlh->messageType); |
523 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); | 510 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); |
524 | 511 | ||
512 | if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg]) | ||
513 | return NF_ACCEPT; | ||
514 | |||
525 | switch (msg) { | 515 | switch (msg) { |
526 | case PPTP_START_SESSION_REQUEST: | 516 | case PPTP_START_SESSION_REQUEST: |
527 | /* client requests for new control session */ | 517 | /* client requests for new control session */ |
@@ -537,11 +527,6 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
537 | break; | 527 | break; |
538 | 528 | ||
539 | case PPTP_OUT_CALL_REQUEST: | 529 | case PPTP_OUT_CALL_REQUEST: |
540 | if (reqlen < sizeof(_pptpReq.ocreq)) { | ||
541 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
542 | break; | ||
543 | } | ||
544 | |||
545 | /* client initiating connection to server */ | 530 | /* client initiating connection to server */ |
546 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | 531 | if (info->sstate != PPTP_SESSION_CONFIRMED) { |
547 | DEBUGP("%s but no session\n", | 532 | DEBUGP("%s but no session\n", |
@@ -555,11 +540,6 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
555 | info->pns_call_id = cid; | 540 | info->pns_call_id = cid; |
556 | break; | 541 | break; |
557 | case PPTP_IN_CALL_REPLY: | 542 | case PPTP_IN_CALL_REPLY: |
558 | if (reqlen < sizeof(_pptpReq.icack)) { | ||
559 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
560 | break; | ||
561 | } | ||
562 | |||
563 | /* client answers incoming call */ | 543 | /* client answers incoming call */ |
564 | if (info->cstate != PPTP_CALL_IN_REQ | 544 | if (info->cstate != PPTP_CALL_IN_REQ |
565 | && info->cstate != PPTP_CALL_IN_REP) { | 545 | && info->cstate != PPTP_CALL_IN_REP) { |
@@ -595,7 +575,6 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
595 | info->cstate = PPTP_CALL_CLEAR_REQ; | 575 | info->cstate = PPTP_CALL_CLEAR_REQ; |
596 | break; | 576 | break; |
597 | case PPTP_SET_LINK_INFO: | 577 | case PPTP_SET_LINK_INFO: |
598 | break; | ||
599 | case PPTP_ECHO_REQUEST: | 578 | case PPTP_ECHO_REQUEST: |
600 | case PPTP_ECHO_REPLY: | 579 | case PPTP_ECHO_REPLY: |
601 | /* I don't have to explain these ;) */ | 580 | /* I don't have to explain these ;) */ |