From b01b61e5a703dcfdf782b3ecc42d2e1aa87ecce4 Mon Sep 17 00:00:00 2001 From: Christian Giese Date: Wed, 5 Jan 2022 14:57:38 +0100 Subject: [PATCH] #63 reject unknown LCP options Reject all unknown LCP configuration options by sending LCP conf-reject. --- src/bbl_protocols.c | 15 +++++++++++++++ src/bbl_protocols.h | 9 ++++++++- src/bbl_rx.c | 46 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/bbl_protocols.c b/src/bbl_protocols.c index 0616b5d4..7e7a932d 100644 --- a/src/bbl_protocols.c +++ b/src/bbl_protocols.c @@ -2774,6 +2774,7 @@ decode_ppp_ip6cp(uint8_t *buf, uint16_t len, uint16_t ip6cp_len = 0; uint8_t ip6cp_option_type = 0; uint8_t ip6cp_option_len = 0; + uint8_t ip6cp_option_index = 0; if(len < 4 || sp_len < sizeof(bbl_ip6cp_t)) { return DECODE_ERROR; @@ -2813,6 +2814,9 @@ decode_ppp_ip6cp(uint8_t *buf, uint16_t len, case PPP_CODE_CONF_ACK: case PPP_CODE_CONF_NAK: while(ip6cp_len >= 2) { + if(ip6cp_option_index < PPP_MAX_OPTIONS) { + ip6cp->option[ip6cp_option_index++] = buf; + } ip6cp_option_type = *buf; BUMP_BUFFER(buf, ip6cp_len, sizeof(uint8_t)); ip6cp_option_len = *buf; @@ -2829,6 +2833,7 @@ decode_ppp_ip6cp(uint8_t *buf, uint16_t len, ip6cp->ipv6_identifier = *(uint64_t*)buf; break; default: + ip6cp->unknown_options = true; break; } BUMP_BUFFER(buf, ip6cp_len, ip6cp_option_len); @@ -2855,6 +2860,7 @@ decode_ppp_ipcp(uint8_t *buf, uint16_t len, uint16_t ipcp_len = 0; uint8_t ipcp_option_type = 0; uint8_t ipcp_option_len = 0; + uint8_t ipcp_option_index = 0; if(len < 4 || sp_len < sizeof(bbl_ipcp_t)) { return DECODE_ERROR; @@ -2894,6 +2900,9 @@ decode_ppp_ipcp(uint8_t *buf, uint16_t len, case PPP_CODE_CONF_ACK: case PPP_CODE_CONF_NAK: while(ipcp_len >= 2) { + if(ipcp_option_index < PPP_MAX_OPTIONS) { + ipcp->option[ipcp_option_index++] = buf; + } ipcp_option_type = *buf; BUMP_BUFFER(buf, ipcp_len, sizeof(uint8_t)); ipcp_option_len = *buf; @@ -2919,6 +2928,7 @@ decode_ppp_ipcp(uint8_t *buf, uint16_t len, ipcp->dns2 = *(uint32_t*)buf; break; default: + ipcp->unknown_options = true; break; } BUMP_BUFFER(buf, ipcp_len, ipcp_option_len); @@ -2953,6 +2963,7 @@ decode_ppp_lcp(uint8_t *buf, uint16_t len, uint16_t lcp_len = 0; uint8_t lcp_option_type = 0; uint8_t lcp_option_len = 0; + uint8_t lcp_option_index = 0; if(len < 4 || sp_len < sizeof(bbl_lcp_t)) { return DECODE_ERROR; @@ -3015,6 +3026,9 @@ decode_ppp_lcp(uint8_t *buf, uint16_t len, case PPP_CODE_CONF_ACK: case PPP_CODE_CONF_NAK: while(lcp_len >= 2) { + if(lcp_option_index < PPP_MAX_OPTIONS) { + lcp->option[lcp_option_index++] = buf; + } lcp_option_type = *buf; BUMP_BUFFER(buf, lcp_len, sizeof(uint8_t)); lcp_option_len = *buf; @@ -3037,6 +3051,7 @@ decode_ppp_lcp(uint8_t *buf, uint16_t len, lcp->magic = *(uint32_t*)buf; break; default: + lcp->unknown_options = true; break; } BUMP_BUFFER(buf, lcp_len, lcp_option_len); diff --git a/src/bbl_protocols.h b/src/bbl_protocols.h index 388bdf90..7936b747 100644 --- a/src/bbl_protocols.h +++ b/src/bbl_protocols.h @@ -100,6 +100,8 @@ #define PPP_CODE_ECHO_REPLY 10 #define PPP_CODE_DISCARD_REQUEST 11 +#define PPP_MAX_OPTIONS 8 + #define PAP_CODE_REQUEST 1 #define PAP_CODE_ACK 2 #define PAP_CODE_NAK 3 @@ -529,7 +531,6 @@ struct pppoe_ppp_session_header { uint16_t protocol; } __attribute__ ((__packed__)); - /* * PPP LCP Structure */ @@ -547,6 +548,8 @@ typedef struct bbl_lcp_ { uint16_t vendor_value_len; uint8_t *start; uint16_t len; + uint8_t *option[PPP_MAX_OPTIONS]; + bool unknown_options; } bbl_lcp_t; /* @@ -563,6 +566,8 @@ typedef struct bbl_ipcp_ { bool option_address; bool option_dns1; bool option_dns2; + uint8_t *option[PPP_MAX_OPTIONS]; + bool unknown_options; } bbl_ipcp_t; /* @@ -574,6 +579,8 @@ typedef struct bbl_ip6cp_ { uint8_t *options; uint8_t options_len; uint64_t ipv6_identifier; + uint8_t *option[PPP_MAX_OPTIONS]; + bool unknown_options; } bbl_ip6cp_t; /* diff --git a/src/bbl_rx.c b/src/bbl_rx.c index 76bdfb80..41eb4faa 100644 --- a/src/bbl_rx.c +++ b/src/bbl_rx.c @@ -1155,7 +1155,48 @@ bbl_rx_ipcp(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_ } } -void +/** + * bbl_rx_lcp_conf_reject + * + * This function rejects all unknown LCP configuration + * options by sending LCP conf-reject. + * + * @param session corresponding session + * @param lcp received LCP packet + */ +static void +bbl_rx_lcp_conf_reject(bbl_session_s *session, bbl_lcp_t *lcp) { + + uint8_t type; + uint8_t len; + session->lcp_options_len = 0; + + for(int i=0; i < PPP_MAX_OPTIONS; i++) { + if(lcp->option[i]) { + type = lcp->option[i][0]; + len = lcp->option[i][1]; + switch (type) { + case PPP_LCP_OPTION_MRU: + case PPP_LCP_OPTION_AUTH: + case PPP_LCP_OPTION_MAGIC: + break; + default: + if((session->lcp_options_len + len) <= PPP_OPTIONS_BUFFER) { + memcpy(&session->lcp_options[session->lcp_options_len], lcp->option[i], len); + session->lcp_options_len += len; + } + break; + } + } + } + session->lcp_peer_identifier = lcp->identifier; + session->lcp_response_code = PPP_CODE_CONF_REJECT; + session->send_requests |= BBL_SEND_LCP_RESPONSE; + bbl_session_tx_qnode_insert(session); + return; +} + +static void bbl_rx_lcp(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_s *session) { bbl_pppoe_session_t *pppoes; bbl_lcp_t *lcp; @@ -1200,6 +1241,9 @@ bbl_rx_lcp(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_s bbl_session_tx_qnode_insert(session); break; case PPP_CODE_CONF_REQUEST: + if(lcp->unknown_options) { + return bbl_rx_lcp_conf_reject(session, lcp); + } session->auth_protocol = lcp->auth; if(session->access_config->authentication_protocol) { if(session->access_config->authentication_protocol != lcp->auth) {