summaryrefslogtreecommitdiff
path: root/accel-pppd
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd')
-rw-r--r--accel-pppd/ppp/ppp_ccp.c42
-rw-r--r--accel-pppd/ppp/ppp_ipcp.c40
-rw-r--r--accel-pppd/ppp/ppp_ipv6cp.c40
-rw-r--r--accel-pppd/ppp/ppp_lcp.c67
4 files changed, 155 insertions, 34 deletions
diff --git a/accel-pppd/ppp/ppp_ccp.c b/accel-pppd/ppp/ppp_ccp.c
index f9e05e89..4dda10f7 100644
--- a/accel-pppd/ppp/ppp_ccp.c
+++ b/accel-pppd/ppp/ppp_ccp.c
@@ -387,10 +387,13 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size)
ccp->ropt_len = size;
while (size > 0) {
+ if (size < sizeof(*hdr))
+ return CCP_OPT_FAIL;
+
hdr = (struct ccp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
- break;
+ if (hdr->len < sizeof(*hdr) || hdr->len > size)
+ return CCP_OPT_FAIL;
ropt = _malloc(sizeof(*ropt));
memset(ropt, 0, sizeof(*ropt));
@@ -482,10 +485,17 @@ static int ccp_recv_conf_rej(struct ppp_ccp_t *ccp, uint8_t *data, int size)
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ccp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ccp->options, entry) {
if (lopt->id == hdr->id) {
@@ -523,10 +533,17 @@ static int ccp_recv_conf_nak(struct ppp_ccp_t *ccp, uint8_t *data, int size)
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ccp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ccp->options, entry) {
if (lopt->id == hdr->id) {
@@ -566,10 +583,17 @@ static int ccp_recv_conf_ack(struct ppp_ccp_t *ccp, uint8_t *data, int size)
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ccp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ccp->options, entry) {
if (lopt->id == hdr->id) {
@@ -647,7 +671,7 @@ static void ccp_recv(struct ppp_handler_t*h)
}
hdr = (struct ccp_hdr_t *)ccp->ppp->buf;
- if (ntohs(hdr->len) < PPP_HEADERLEN) {
+ if (ntohs(hdr->len) < PPP_HEADERLEN || ntohs(hdr->len) > ccp->ppp->buf_size - 2) {
log_ppp_warn("CCP: short packet received\n");
return;
}
@@ -695,8 +719,10 @@ static void ccp_recv(struct ppp_handler_t*h)
ppp_fsm_recv_conf_ack(&ccp->fsm);
break;
case CONFNAK:
- ccp_recv_conf_nak(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN);
- ppp_fsm_recv_conf_rej(&ccp->fsm);
+ if (ccp_recv_conf_nak(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN))
+ ap_session_terminate(&ccp->ppp->ses, TERM_USER_ERROR, 0);
+ else
+ ppp_fsm_recv_conf_rej(&ccp->fsm);
break;
case CONFREJ:
if (ccp_recv_conf_rej(ccp, (uint8_t*)(hdr + 1),ntohs(hdr->len) - PPP_HDRLEN))
diff --git a/accel-pppd/ppp/ppp_ipcp.c b/accel-pppd/ppp/ppp_ipcp.c
index 416fba93..b67bfa44 100644
--- a/accel-pppd/ppp/ppp_ipcp.c
+++ b/accel-pppd/ppp/ppp_ipcp.c
@@ -391,10 +391,13 @@ static int ipcp_recv_conf_req(struct ppp_ipcp_t *ipcp, uint8_t *data, int size)
ipcp->ropt_len = size;
while (size > 0) {
+ if (size < sizeof(*hdr))
+ return IPCP_OPT_FAIL;
+
hdr = (struct ipcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
- break;
+ if (hdr->len < sizeof(*hdr) || hdr->len > size)
+ return IPCP_OPT_FAIL;
ropt = _malloc(sizeof(*ropt));
memset(ropt, 0, sizeof(*ropt));
@@ -503,10 +506,17 @@ static int ipcp_recv_conf_rej(struct ppp_ipcp_t *ipcp, uint8_t *data, int size)
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ipcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ipcp->options, entry) {
if (lopt->id == hdr->id) {
@@ -544,10 +554,17 @@ static int ipcp_recv_conf_nak(struct ppp_ipcp_t *ipcp, uint8_t *data, int size)
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ipcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ipcp->options, entry) {
if (lopt->id == hdr->id) {
@@ -587,10 +604,17 @@ static int ipcp_recv_conf_ack(struct ppp_ipcp_t *ipcp, uint8_t *data, int size)
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ipcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ipcp->options, entry) {
if (lopt->id == hdr->id) {
@@ -725,8 +749,10 @@ static void ipcp_recv(struct ppp_handler_t*h)
ppp_fsm_recv_conf_ack(&ipcp->fsm);
break;
case CONFNAK:
- ipcp_recv_conf_nak(ipcp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN);
- ppp_fsm_recv_conf_rej(&ipcp->fsm);
+ if (ipcp_recv_conf_nak(ipcp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN))
+ ap_session_terminate(&ipcp->ppp->ses, TERM_USER_ERROR, 0);
+ else
+ ppp_fsm_recv_conf_rej(&ipcp->fsm);
break;
case CONFREJ:
if (ipcp_recv_conf_rej(ipcp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN))
diff --git a/accel-pppd/ppp/ppp_ipv6cp.c b/accel-pppd/ppp/ppp_ipv6cp.c
index 7f278daa..755e8903 100644
--- a/accel-pppd/ppp/ppp_ipv6cp.c
+++ b/accel-pppd/ppp/ppp_ipv6cp.c
@@ -395,10 +395,13 @@ static int ipv6cp_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int
ipv6cp->ropt_len = size;
while (size > 0) {
+ if (size < sizeof(*hdr))
+ return IPV6CP_OPT_FAIL;
+
hdr = (struct ipv6cp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
- break;
+ if (hdr->len < sizeof(*hdr) || hdr->len > size)
+ return IPV6CP_OPT_FAIL;
ropt = _malloc(sizeof(*ropt));
memset(ropt, 0, sizeof(*ropt));
@@ -507,10 +510,17 @@ static int ipv6cp_recv_conf_rej(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ipv6cp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ipv6cp->options, entry) {
if (lopt->id == hdr->id) {
@@ -548,10 +558,17 @@ static int ipv6cp_recv_conf_nak(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ipv6cp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ipv6cp->options, entry) {
if (lopt->id == hdr->id) {
@@ -591,10 +608,17 @@ static int ipv6cp_recv_conf_ack(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int
}*/
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct ipv6cp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &ipv6cp->options, entry) {
if (lopt->id == hdr->id) {
@@ -729,8 +753,10 @@ static void ipv6cp_recv(struct ppp_handler_t*h)
ppp_fsm_recv_conf_ack(&ipv6cp->fsm);
break;
case CONFNAK:
- ipv6cp_recv_conf_nak(ipv6cp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN);
- ppp_fsm_recv_conf_rej(&ipv6cp->fsm);
+ if (ipv6cp_recv_conf_nak(ipv6cp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN))
+ ap_session_terminate(&ipv6cp->ppp->ses, TERM_USER_ERROR, 0);
+ else
+ ppp_fsm_recv_conf_rej(&ipv6cp->fsm);
break;
case CONFREJ:
if (ipv6cp_recv_conf_rej(ipv6cp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN))
diff --git a/accel-pppd/ppp/ppp_lcp.c b/accel-pppd/ppp/ppp_lcp.c
index ed085b3b..fb0bb8bb 100644
--- a/accel-pppd/ppp/ppp_lcp.c
+++ b/accel-pppd/ppp/ppp_lcp.c
@@ -47,6 +47,22 @@ static void send_term_req(struct ppp_fsm_t *fsm);
static void send_term_ack(struct ppp_fsm_t *fsm);
static void lcp_recv(struct ppp_handler_t*);
+static uint16_t lcp_read_u16(const void *ptr)
+{
+ uint16_t value;
+
+ memcpy(&value, ptr, sizeof(value));
+ return ntohs(value);
+}
+
+static uint32_t lcp_read_u32(const void *ptr)
+{
+ uint32_t value;
+
+ memcpy(&value, ptr, sizeof(value));
+ return ntohl(value);
+}
+
static void lcp_options_init(struct ppp_lcp_t *lcp)
{
struct lcp_option_t *lopt;
@@ -370,10 +386,13 @@ static int lcp_recv_conf_req(struct ppp_lcp_t *lcp, uint8_t *data, int size)
lcp->ropt_len = size;
while (size > 0) {
+ if (size < sizeof(*hdr))
+ return LCP_OPT_FAIL;
+
hdr = (struct lcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
- break;
+ if (hdr->len < sizeof(*hdr) || hdr->len > size)
+ return LCP_OPT_FAIL;
ropt = _malloc(sizeof(*ropt));
memset(ropt, 0, sizeof(*ropt));
@@ -462,10 +481,17 @@ static int lcp_recv_conf_rej(struct ppp_lcp_t *lcp, uint8_t *data, int size)
}
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct lcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &lcp->options, entry) {
if (lopt->id == hdr->id) {
@@ -507,10 +533,17 @@ static int lcp_recv_conf_nak(struct ppp_lcp_t *lcp, uint8_t *data, int size)
}
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct lcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt,&lcp->options,entry) {
if (lopt->id == hdr->id) {
@@ -550,10 +583,17 @@ static int lcp_recv_conf_ack(struct ppp_lcp_t *lcp, uint8_t *data, int size)
}
while (size > 0) {
+ if (size < sizeof(*hdr)) {
+ res = -1;
+ break;
+ }
+
hdr = (struct lcp_opt_hdr_t *)data;
- if (!hdr->len || hdr->len > size)
+ if (hdr->len < sizeof(*hdr) || hdr->len > size) {
+ res = -1;
break;
+ }
list_for_each_entry(lopt, &lcp->options, entry) {
if (lopt->id == hdr->id) {
@@ -587,7 +627,7 @@ static void lcp_recv_echo_repl(struct ppp_lcp_t *lcp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_debug("recv [LCP EchoRep id=%x]\n", lcp->fsm.recv_id);
} else {
- magic = ntohl(*(uint32_t *)data);
+ magic = lcp_read_u32(data);
if (conf_ppp_verbose)
log_ppp_debug("recv [LCP EchoRep id=%x <magic %08x>]\n", lcp->fsm.recv_id, magic);
@@ -746,7 +786,7 @@ static void lcp_recv(struct ppp_handler_t*h)
hdr = (struct lcp_hdr_t *)lcp->ppp->buf;
len = ntohs(hdr->len);
buf_len = lcp->ppp->buf_size;
- if (len < PPP_HEADERLEN) {
+ if (len < PPP_HEADERLEN || len > lcp->ppp->buf_size - 2) {
log_ppp_warn("LCP: short packet received\n");
return;
}
@@ -802,7 +842,10 @@ static void lcp_recv(struct ppp_handler_t*h)
}
break;
case CONFNAK:
- lcp_recv_conf_nak(lcp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN);
+ if (lcp_recv_conf_nak(lcp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) {
+ ap_session_terminate(&lcp->ppp->ses, TERM_USER_ERROR, 0);
+ break;
+ }
if (lcp->fsm.recv_id != lcp->fsm.id)
break;
ppp_fsm_recv_conf_rej(&lcp->fsm);
@@ -838,7 +881,7 @@ static void lcp_recv(struct ppp_handler_t*h)
break;
}
if (conf_ppp_verbose)
- log_ppp_debug("recv [LCP EchoReq id=%x <magic %08x>]\n", hdr->id, ntohl(*(uint32_t*)(hdr + 1)));
+ log_ppp_debug("recv [LCP EchoReq id=%x <magic %08x>]\n", hdr->id, lcp_read_u32(hdr + 1));
send_echo_reply(lcp);
break;
case ECHOREP:
@@ -854,11 +897,11 @@ static void lcp_recv(struct ppp_handler_t*h)
log_ppp_warn("LCP: short ProtoRej received\n");
break;
}
- log_ppp_info2("recv [LCP ProtoRej id=%x <%04x>]\n", hdr->id, ntohs(*(uint16_t*)(hdr + 1)));
+ log_ppp_info2("recv [LCP ProtoRej id=%x <%04x>]\n", hdr->id, lcp_read_u16(hdr + 1));
}
if (len < PPP_HDRLEN + 2 || buf_len < (int)(sizeof(*hdr) + 2))
break;
- ppp_recv_proto_rej(lcp->ppp, ntohs(*(uint16_t *)(hdr + 1)));
+ ppp_recv_proto_rej(lcp->ppp, lcp_read_u16(hdr + 1));
break;
case DISCARDREQ:
if (conf_ppp_verbose) {
@@ -866,7 +909,7 @@ static void lcp_recv(struct ppp_handler_t*h)
log_ppp_warn("LCP: short DiscardReq received\n");
break;
}
- log_ppp_info2("recv [LCP DiscardReq id=%x <magic %08x>]\n", hdr->id, ntohl(*(uint32_t*)(hdr + 1)));
+ log_ppp_info2("recv [LCP DiscardReq id=%x <magic %08x>]\n", hdr->id, lcp_read_u32(hdr + 1));
}
break;
case IDENT: