[PFCP/GTP] Fixed security bug (#2127,#2128,#2129)

This commit is contained in:
Sukchan Lee 2023-03-05 08:35:30 +09:00
parent 62b6b42e88
commit fd9c211005
12 changed files with 177 additions and 149 deletions

View File

@ -587,8 +587,8 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
break;
}
default:
ogs_assert_if_reached();
break;
ogs_error("Unknown type[%d]", desc->ctype);
return OGS_ERROR;
}
return OGS_OK;

View File

@ -21,7 +21,7 @@
/*******************************************************************************
* This file had been created by gtp1-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2022-06-30 08:56:31.641366 by ubuntu
* Created on: 2023-03-05 00:10:59.164127 by acetcom
* from 29060-g00.docx
******************************************************************************/
@ -2284,7 +2284,10 @@ int ogs_gtp1_parse_msg(ogs_gtp1_message_t *gtp1_message, ogs_pkbuf_t *pkbuf)
else
size = OGS_GTPV1C_HEADER_LEN - 4;
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
if (ogs_pkbuf_pull(pkbuf, size) == NULL) {
ogs_error("ogs_pkbuf_pull() failed [len:%d]", pkbuf->len);
return OGS_ERROR;
}
memcpy(&gtp1_message->h, pkbuf->data - size, size);
gtp1_message->h.teid = be32toh(gtp1_message->h.teid);

View File

@ -21,7 +21,7 @@
/*******************************************************************************
* This file had been created by gtp1-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2022-06-30 08:56:31.627300 by ubuntu
* Created on: 2023-03-05 00:10:59.158386 by acetcom
* from 29060-g00.docx
******************************************************************************/

View File

@ -614,7 +614,10 @@ f.write("""int ogs_gtp1_parse_msg(ogs_gtp1_message_t *gtp1_message, ogs_pkbuf_t
else
size = OGS_GTPV1C_HEADER_LEN - 4;
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
if (ogs_pkbuf_pull(pkbuf, size) == NULL) {
ogs_error("ogs_pkbuf_pull() failed [len:%d]", pkbuf->len);
return OGS_ERROR;
}
memcpy(&gtp1_message->h, pkbuf->data - size, size);
gtp1_message->h.teid = be32toh(gtp1_message->h.teid);

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2022-06-30 08:56:57.201419 by ubuntu
* Created on: 2023-03-05 00:10:47.974480 by acetcom
* from 29274-g30.docx
******************************************************************************/
@ -2709,7 +2709,10 @@ int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp2_message, ogs_pkbuf_t *pkbuf)
else
size = OGS_GTPV2C_HEADER_LEN-OGS_GTP2_TEID_LEN;
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
if (ogs_pkbuf_pull(pkbuf, size) == NULL) {
ogs_error("ogs_pkbuf_pull() failed [len:%d]", pkbuf->len);
return OGS_ERROR;
}
memcpy(&gtp2_message->h, pkbuf->data - size, size);
if (h->teid_presence)

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2022-06-30 08:56:57.190289 by ubuntu
* Created on: 2023-03-05 00:10:47.969299 by acetcom
* from 29274-g30.docx
******************************************************************************/

View File

@ -702,7 +702,10 @@ f.write("""int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp2_message, ogs_pkbuf_t
else
size = OGS_GTPV2C_HEADER_LEN-OGS_GTP2_TEID_LEN;
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
if (ogs_pkbuf_pull(pkbuf, size) == NULL) {
ogs_error("ogs_pkbuf_pull() failed [len:%d]", pkbuf->len);
return OGS_ERROR;
}
memcpy(&gtp2_message->h, pkbuf->data - size, size);
if (h->teid_presence)

View File

@ -38,8 +38,6 @@ static ogs_gtp_xact_stage_t ogs_gtp2_xact_get_stage(uint8_t type, uint32_t xid);
static ogs_gtp_xact_stage_t ogs_gtp1_xact_get_stage(uint8_t type, uint32_t xid);
static int ogs_gtp_xact_delete(ogs_gtp_xact_t *xact);
static int ogs_gtp_xact_update_rx(ogs_gtp_xact_t *xact, uint8_t type);
static ogs_gtp_xact_t *ogs_gtp_xact_find_by_xid(
ogs_gtp_node_t *gnode, uint8_t type, uint8_t gtp_version, uint32_t xid);
static void response_timeout(void *data);
static void holding_timeout(void *data);
@ -806,21 +804,61 @@ static void holding_timeout(void *data)
int ogs_gtp1_xact_receive(
ogs_gtp_node_t *gnode, ogs_gtp1_header_t *h, ogs_gtp_xact_t **xact)
{
char buf[OGS_ADDRSTRLEN];
int rv;
char buf[OGS_ADDRSTRLEN];
uint8_t type;
uint32_t sqn, xid;
ogs_gtp_xact_stage_t stage;
ogs_list_t *list = NULL;
ogs_gtp_xact_t *new = NULL;
uint16_t sqn;
ogs_assert(gnode);
ogs_assert(h);
type = h->type;
if (!h->s) {
ogs_error("ogs_gtp_xact_update_rx() failed, pkt has no SQN");
return OGS_ERROR;
}
sqn = h->sqn;
new = ogs_gtp_xact_find_by_xid(gnode, h->type, 1, OGS_GTP1_SQN_TO_XID(sqn));
xid = OGS_GTP1_SQN_TO_XID(sqn);
stage = ogs_gtp1_xact_get_stage(type, xid);
switch (stage) {
case GTP_XACT_INITIAL_STAGE:
list = &gnode->remote_list;
break;
case GTP_XACT_INTERMEDIATE_STAGE:
list = &gnode->local_list;
break;
case GTP_XACT_FINAL_STAGE:
list = &gnode->local_list; // FIXME: is this correct?
break;
default:
ogs_error("[%d] Unexpected type %u from GTPv1 peer [%s]:%d",
xid, type, OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
return OGS_ERROR;
}
ogs_assert(list);
ogs_list_for_each(list, new) {
if (new->gtp_version == 1 && new->xid == xid) {
ogs_debug("[%d] %s Find GTPv%u peer [%s]:%d",
new->xid,
new->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
new->gtp_version,
OGS_ADDR(&gnode->addr, buf),
OGS_PORT(&gnode->addr));
break;
}
}
ogs_debug("[%d] Cannot find xact type %u from GTPv1 peer [%s]:%d",
xid, type, OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
if (!new)
new = ogs_gtp_xact_remote_create(gnode, 1, sqn);
ogs_assert(new);
@ -831,7 +869,7 @@ int ogs_gtp1_xact_receive(
OGS_ADDR(&gnode->addr, buf),
OGS_PORT(&gnode->addr));
rv = ogs_gtp_xact_update_rx(new, h->type);
rv = ogs_gtp_xact_update_rx(new, type);
if (rv == OGS_ERROR) {
ogs_error("ogs_gtp_xact_update_rx() failed");
ogs_gtp_xact_delete(new);
@ -847,18 +885,69 @@ int ogs_gtp1_xact_receive(
int ogs_gtp_xact_receive(
ogs_gtp_node_t *gnode, ogs_gtp2_header_t *h, ogs_gtp_xact_t **xact)
{
char buf[OGS_ADDRSTRLEN];
int rv;
char buf[OGS_ADDRSTRLEN];
uint8_t type;
uint32_t sqn, xid;
ogs_gtp_xact_stage_t stage;
ogs_list_t *list = NULL;
ogs_gtp_xact_t *new = NULL;
uint32_t sqn;
ogs_assert(gnode);
ogs_assert(h);
type = h->type;
if (h->teid_presence) sqn = h->sqn;
else sqn = h->sqn_only;
new = ogs_gtp_xact_find_by_xid(gnode, h->type, 2, OGS_GTP2_SQN_TO_XID(sqn));
xid = OGS_GTP2_SQN_TO_XID(sqn);
stage = ogs_gtp2_xact_get_stage(type, xid);
switch (stage) {
case GTP_XACT_INITIAL_STAGE:
list = &gnode->remote_list;
break;
case GTP_XACT_INTERMEDIATE_STAGE:
list = &gnode->local_list;
break;
case GTP_XACT_FINAL_STAGE:
if (xid & OGS_GTP_CMD_XACT_ID) {
if (type == OGS_GTP2_MODIFY_BEARER_FAILURE_INDICATION_TYPE ||
type == OGS_GTP2_DELETE_BEARER_FAILURE_INDICATION_TYPE ||
type == OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE) {
list = &gnode->local_list;
} else {
list = &gnode->remote_list;
}
} else {
list = &gnode->local_list;
}
break;
default:
ogs_error("[%d] Unexpected type %u from GTPv2 peer [%s]:%d",
xid, type, OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
return OGS_ERROR;
}
ogs_assert(list);
ogs_list_for_each(list, new) {
if (new->gtp_version == 2 && new->xid == xid) {
ogs_debug("[%d] %s Find GTPv%u peer [%s]:%d",
new->xid,
new->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
new->gtp_version,
OGS_ADDR(&gnode->addr, buf),
OGS_PORT(&gnode->addr));
break;
}
}
ogs_debug("[%d] Cannot find xact type %u from GTPv2 peer [%s]:%d",
xid, type,
OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
if (!new)
new = ogs_gtp_xact_remote_create(gnode, 2, sqn);
ogs_assert(new);
@ -869,7 +958,7 @@ int ogs_gtp_xact_receive(
OGS_ADDR(&gnode->addr, buf),
OGS_PORT(&gnode->addr));
rv = ogs_gtp_xact_update_rx(new, h->type);
rv = ogs_gtp_xact_update_rx(new, type);
if (rv == OGS_ERROR) {
ogs_error("ogs_gtp_xact_update_rx() failed");
ogs_gtp_xact_delete(new);
@ -1011,75 +1100,6 @@ static ogs_gtp_xact_stage_t ogs_gtp2_xact_get_stage(uint8_t type, uint32_t xid)
return stage;
}
static ogs_gtp_xact_t *ogs_gtp_xact_find_by_xid(
ogs_gtp_node_t *gnode, uint8_t type, uint8_t gtp_version, uint32_t xid)
{
char buf[OGS_ADDRSTRLEN];
ogs_list_t *list = NULL;
ogs_gtp_xact_t *xact = NULL;
ogs_gtp_xact_stage_t stage;
ogs_assert(gnode);
if (gtp_version == 1)
stage = ogs_gtp1_xact_get_stage(type, xid);
else
stage = ogs_gtp2_xact_get_stage(type, xid);
switch (stage) {
case GTP_XACT_INITIAL_STAGE:
list = &gnode->remote_list;
break;
case GTP_XACT_INTERMEDIATE_STAGE:
list = &gnode->local_list;
break;
case GTP_XACT_FINAL_STAGE:
switch (gtp_version) {
case 1:
list = &gnode->local_list; // FIXME: is this correct?
break;
case 2:
default:
if (xid & OGS_GTP_CMD_XACT_ID) {
if (type == OGS_GTP2_MODIFY_BEARER_FAILURE_INDICATION_TYPE ||
type == OGS_GTP2_DELETE_BEARER_FAILURE_INDICATION_TYPE ||
type == OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE) {
list = &gnode->local_list;
} else {
list = &gnode->remote_list;
}
} else {
list = &gnode->local_list;
}
break;
}
break;
default:
ogs_warn("Unexpected stage %u.", stage);
ogs_assert_if_reached();
return NULL;
}
ogs_assert(list);
ogs_list_for_each(list, xact) {
if (xact->gtp_version == gtp_version && xact->xid == xid) {
ogs_debug("[%d] %s Find GTPv%u peer [%s]:%d",
xact->xid,
xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
xact->gtp_version,
OGS_ADDR(&gnode->addr, buf),
OGS_PORT(&gnode->addr));
return xact;
}
}
ogs_debug("[%d] Cannot find xact type %u from GTPv%u peer [%s]:%d",
xid, type, gtp_version,
OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
return NULL;
}
void ogs_gtp_xact_associate(ogs_gtp_xact_t *xact1, ogs_gtp_xact_t *xact2)
{
ogs_assert(xact1);

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by pfcp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2023-01-10 12:02:27.807637 by mitmitmitm
* Created on: 2023-03-05 00:10:36.112946 by acetcom
* from 29244-g91-modified.docx
******************************************************************************/
@ -4006,7 +4006,11 @@ ogs_pfcp_message_t *ogs_pfcp_parse_msg(ogs_pkbuf_t *pkbuf)
else
size = OGS_PFCP_HEADER_LEN-OGS_PFCP_SEID_LEN;
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
if (ogs_pkbuf_pull(pkbuf, size) == NULL) {
ogs_error("ogs_pkbuf_pull() failed [len:%d]", pkbuf->len);
ogs_pfcp_message_free(pfcp_message);
return NULL;
}
memcpy(&pfcp_message->h, pkbuf->data - size, size);
if (h->seid_presence) {

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by pfcp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2023-01-10 12:02:27.782476 by mitmitmitm
* Created on: 2023-03-05 00:10:36.099999 by acetcom
* from 29244-g91-modified.docx
******************************************************************************/

View File

@ -790,7 +790,11 @@ f.write("""ogs_pfcp_message_t *ogs_pfcp_parse_msg(ogs_pkbuf_t *pkbuf)
else
size = OGS_PFCP_HEADER_LEN-OGS_PFCP_SEID_LEN;
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
if (ogs_pkbuf_pull(pkbuf, size) == NULL) {
ogs_error("ogs_pkbuf_pull() failed [len:%d]", pkbuf->len);
ogs_pfcp_message_free(pfcp_message);
return NULL;
}
memcpy(&pfcp_message->h, pkbuf->data - size, size);
if (h->seid_presence) {

View File

@ -41,9 +41,6 @@ static ogs_pfcp_xact_stage_t ogs_pfcp_xact_get_stage(
uint8_t type, uint32_t xid);
static int ogs_pfcp_xact_delete(ogs_pfcp_xact_t *xact);
static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type);
static ogs_pfcp_xact_t *ogs_pfcp_xact_find_by_xid(
ogs_pfcp_node_t *node, uint8_t type, uint32_t xid);
static void response_timeout(void *data);
static void holding_timeout(void *data);
@ -669,17 +666,56 @@ static void delayed_commit_timeout(void *data)
int ogs_pfcp_xact_receive(
ogs_pfcp_node_t *node, ogs_pfcp_header_t *h, ogs_pfcp_xact_t **xact)
{
char buf[OGS_ADDRSTRLEN];
int rv;
char buf[OGS_ADDRSTRLEN];
uint8_t type;
uint32_t sqn, xid;
ogs_pfcp_xact_stage_t stage;
ogs_list_t *list = NULL;
ogs_pfcp_xact_t *new = NULL;
ogs_assert(node);
ogs_assert(h);
new = ogs_pfcp_xact_find_by_xid(
node, h->type, OGS_PFCP_SQN_TO_XID(h->sqn));
type = h->type;
sqn = h->sqn;
xid = OGS_PFCP_SQN_TO_XID(sqn);
stage = ogs_pfcp_xact_get_stage(type, xid);
switch (stage) {
case PFCP_XACT_INITIAL_STAGE:
list = &node->remote_list;
break;
case PFCP_XACT_INTERMEDIATE_STAGE:
list = &node->local_list;
break;
case PFCP_XACT_FINAL_STAGE:
list = &node->local_list;
break;
default:
ogs_error("[%d] Unexpected type %u from PFCP peer [%s]:%d",
xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr));
return OGS_ERROR;
}
ogs_assert(list);
ogs_list_for_each(list, new) {
if (new->xid == xid) {
ogs_debug("[%d] %s Find peer [%s]:%d",
new->xid,
new->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
OGS_ADDR(&node->addr, buf),
OGS_PORT(&node->addr));
break;
}
}
ogs_debug("[%d] Cannot find new type %u from PFCP peer [%s]:%d",
xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr));
if (!new)
new = ogs_pfcp_xact_remote_create(node, h->sqn);
new = ogs_pfcp_xact_remote_create(node, sqn);
ogs_assert(new);
ogs_debug("[%d] %s Receive peer [%s]:%d",
@ -688,7 +724,7 @@ int ogs_pfcp_xact_receive(
OGS_ADDR(&node->addr, buf),
OGS_PORT(&node->addr));
rv = ogs_pfcp_xact_update_rx(new, h->type);
rv = ogs_pfcp_xact_update_rx(new, type);
if (rv == OGS_ERROR) {
ogs_error("ogs_pfcp_xact_update_rx() failed");
ogs_pfcp_xact_delete(new);
@ -736,54 +772,6 @@ static ogs_pfcp_xact_stage_t ogs_pfcp_xact_get_stage(uint8_t type, uint32_t xid)
return stage;
}
static ogs_pfcp_xact_t *ogs_pfcp_xact_find_by_xid(
ogs_pfcp_node_t *node, uint8_t type, uint32_t xid)
{
char buf[OGS_ADDRSTRLEN];
ogs_list_t *list = NULL;
ogs_pfcp_xact_t *xact = NULL;
ogs_pfcp_xact_stage_t stage;
ogs_assert(node);
stage = ogs_pfcp_xact_get_stage(type, xid);
switch (stage) {
case PFCP_XACT_INITIAL_STAGE:
list = &node->remote_list;
break;
case PFCP_XACT_INTERMEDIATE_STAGE:
list = &node->local_list;
break;
case PFCP_XACT_FINAL_STAGE:
list = &node->local_list;
break;
default:
ogs_warn("Unexpected stage %u.", stage);
ogs_assert_if_reached();
return NULL;
}
ogs_assert(list);
ogs_list_for_each(list, xact) {
if (xact->xid == xid) {
ogs_debug("[%d] %s Find peer [%s]:%d",
xact->xid,
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
OGS_ADDR(&node->addr, buf),
OGS_PORT(&node->addr));
return xact;
}
}
ogs_debug("[%d] Cannot find xact type %u from PFCP peer [%s]:%d",
xid, type,
OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr));
return NULL;
}
static int ogs_pfcp_xact_delete(ogs_pfcp_xact_t *xact)
{
char buf[OGS_ADDRSTRLEN];