pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/43394?usp=email )
Change subject: xua_rkm: Validate IE lengths of RKM inner messages ......................................................................
xua_rkm: Validate IE lengths of RKM inner messages
Change-Id: Ibe7e446b1a537c0c09f8049add3460e37cdd58e8 --- M src/m3ua.c M src/xua_internal.h M src/xua_msg.c M src/xua_msg.h M src/xua_rkm.c 5 files changed, 140 insertions(+), 39 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/94/43394/1
diff --git a/src/m3ua.c b/src/m3ua.c index d1a7e27..46282c4 100644 --- a/src/m3ua.c +++ b/src/m3ua.c @@ -202,14 +202,32 @@ XUA_MSG_PART_CLASS(M3UA_IEI_ROUT_KEY, (mandatory), 0, UINT16_MAX)
#define M3UA_MSG_PART_CLASS_REG_RESULT(mandatory) \ - XUA_MSG_PART_CLASS(M3UA_IEI_REG_RESULT, (mandatory), 0, UINT16_MAX) + XUA_MSG_PART_CLASS(M3UA_IEI_REG_RESULT, (mandatory), 24, UINT16_MAX)
#define M3UA_MSG_PART_CLASS_DEREG_RESULT(mandatory) \ - XUA_MSG_PART_CLASS(M3UA_IEI_DEREG_RESULT, (mandatory), 0, UINT16_MAX) + XUA_MSG_PART_CLASS(M3UA_IEI_DEREG_RESULT, (mandatory), 16, UINT16_MAX) + +#define M3UA_MSG_PART_CLASS_LOC_RKEY_ID(mandatory) \ + XUA_MSG_PART_CLASS_U32(M3UA_IEI_LOC_RKEY_ID, (mandatory)) + +#define M3UA_MSG_PART_CLASS_DEST_PC(mandatory) \ + XUA_MSG_PART_CLASS_U32(M3UA_IEI_DEST_PC, (mandatory)) + +#define M3UA_MSG_PART_CLASS_SVC_IND(mandatory) \ + XUA_MSG_PART_CLASS(M3UA_IEI_SVC_IND, (mandatory), 0, UINT16_MAX) + +#define M3UA_MSG_PART_CLASS_ORIG_PC(mandatory) \ + XUA_MSG_PART_CLASS(M3UA_IEI_ORIG_PC, (mandatory), 0, UINT16_MAX)
#define M3UA_MSG_PART_CLASS_PROT_DATA(mandatory) \ XUA_MSG_PART_CLASS(M3UA_IEI_PROT_DATA, (mandatory), 0, UINT16_MAX)
+#define M3UA_MSG_PART_CLASS_REG_STATUS(mandatory) \ + XUA_MSG_PART_CLASS_U32(M3UA_IEI_REG_STATUS, (mandatory)) + +#define M3UA_MSG_PART_CLASS_DEREG_STATUS(mandatory) \ + XUA_MSG_PART_CLASS_U32(M3UA_IEI_DEREG_STATUS, (mandatory)) + /* XFER */ static const struct xua_msg_part_class data_ies[] = { M3UA_MSG_PART_CLASS_NET_APPEAR(false), @@ -452,6 +470,34 @@ }, };
+/* Inner RKM messages: RKM REG REQ "Routing Key" */ +const struct xua_msg_part_class m3ua_rkm_reg_req_routing_key_ies[] = { + M3UA_MSG_PART_CLASS_LOC_RKEY_ID(true), + M3UA_MSG_PART_CLASS_ROUTE_CTX1(false), + M3UA_MSG_PART_CLASS_TRAF_MODE_TYP(false), + M3UA_MSG_PART_CLASS_DEST_PC(true), + M3UA_MSG_PART_CLASS_NET_APPEAR(false), + M3UA_MSG_PART_CLASS_SVC_IND(false), + M3UA_MSG_PART_CLASS_ORIG_PC(false), + XUA_MSG_PART_CLASS_EOF +}; + +/* Inner RKM messages: RKM REG RSP "Registration Result" */ +const struct xua_msg_part_class m3ua_rkm_reg_rsp_registration_result_ies[] = { + M3UA_MSG_PART_CLASS_LOC_RKEY_ID(true), + M3UA_MSG_PART_CLASS_ROUTE_CTX1(true), + M3UA_MSG_PART_CLASS_REG_STATUS(true), + XUA_MSG_PART_CLASS_EOF +}; + + +/* Inner RKM messages: RKM DEREG RSP "Deregistration Result" */ +const struct xua_msg_part_class m3ua_rkm_dereg_rsp_deregistration_result_ies[] = { + M3UA_MSG_PART_CLASS_ROUTE_CTX1(true), + M3UA_MSG_PART_CLASS_DEREG_STATUS(true), + XUA_MSG_PART_CLASS_EOF +}; + /* M3UA dialect of XUA, MGMT,XFER,SNM,ASPSM,ASPTM,RKM */ const struct xua_dialect xua_dialect_m3ua = { .name = "M3UA", diff --git a/src/xua_internal.h b/src/xua_internal.h index 5195b35..47c4974 100644 --- a/src/xua_internal.h +++ b/src/xua_internal.h @@ -90,6 +90,9 @@ extern const struct xua_msg_class m3ua_msg_class_rkm; extern const struct xua_msg_class m3ua_msg_class_aspsm; extern const struct xua_msg_class m3ua_msg_class_asptm; +extern const struct xua_msg_part_class m3ua_rkm_reg_req_routing_key_ies[]; +extern const struct xua_msg_part_class m3ua_rkm_reg_rsp_registration_result_ies[]; +extern const struct xua_msg_part_class m3ua_rkm_dereg_rsp_deregistration_result_ies[];
extern const struct value_string m3ua_snm_msgt_names[]; extern const struct value_string m3ua_err_names[]; diff --git a/src/xua_msg.c b/src/xua_msg.c index 44b173d..1b37c89 100644 --- a/src/xua_msg.c +++ b/src/xua_msg.c @@ -535,6 +535,47 @@ return buf; }
+ +/* Validate incoming xua_msg. returns 0 on success, M3UA_ERR_* on failure. */ +int xua_dialect_check_all_ies_ext(const struct xua_dialect *dialect, const struct xua_msg_class *xmc, + uint8_t msg_type, const struct xua_msg_part_class *ies, + const struct xua_msg *xua, bool repeated_parts) +{ + const struct xua_msg_part_class *ie; + + for (ie = ies; ie->tag; ie = ies++) { + struct xua_msg_part *part; + bool found = false; + llist_for_each_entry(part, &xua->headers, entry) { + if (part->tag != ie->tag) + continue; + found = true; + if (part->len < ie->len_min || part->len > ie->len_max) { + LOGP(dialect->log_subsys, LOGL_ERROR, + "%s Message %s:%s IE %s length %" PRIu16 + " out of range [%" PRIu16 ", %" PRIu16 "]\n", + dialect->name, xmc->name, + xua_class_msg_name(xmc, msg_type), + xua_class_iei_name(xmc, ie->tag), + part->len, ie->len_min, ie->len_max); + return M3UA_ERR_PARAM_FIELD_ERR; + } + if (!repeated_parts) + break; + } + if (ie->mandatory && !found) { + LOGP(dialect->log_subsys, LOGL_ERROR, + "%s Message %s:%s should contain IE %s, but doesn't\n", + dialect->name, xmc->name, + xua_class_msg_name(xmc, msg_type), + xua_class_iei_name(xmc, ie->tag)); + return M3UA_ERR_MISSING_PARAM; + } + } + + return 0; +} + /* Validate incoming xua_msg. returns 0 on success, M3UA_ERR_* on failure. */ int xua_dialect_check_all_ies(const struct xua_dialect *dialect, const struct xua_msg *xua) { @@ -542,7 +583,6 @@ uint8_t msg_type = xua->hdr.msg_type; const struct xua_msg_class *xmc = dialect->class[msg_class]; const struct xua_msg_part_class *ies; - const struct xua_msg_part_class *ie;
/* unknown class? */ if (!xmc) @@ -553,32 +593,7 @@ if (!ies) return 0;
- for (ie = ies; ie->tag; ie = ies++) { - struct xua_msg_part *part = xua_msg_find_tag(xua, ie->tag); - if (!part) { - if (!ie->mandatory) - continue; - LOGP(dialect->log_subsys, LOGL_ERROR, - "%s Message %s:%s should contain IE %s, but doesn't\n", - dialect->name, xmc->name, - xua_class_msg_name(xmc, msg_type), - xua_class_iei_name(xmc, ie->tag)); - return M3UA_ERR_MISSING_PARAM; - } - - if (part->len < ie->len_min || part->len > ie->len_max) { - LOGP(dialect->log_subsys, LOGL_ERROR, - "%s Message %s:%s IE %s length %" PRIu16 - " out of range [%" PRIu16 ", %" PRIu16 "]\n", - dialect->name, xmc->name, - xua_class_msg_name(xmc, msg_type), - xua_class_iei_name(xmc, ie->tag), - part->len, ie->len_min, ie->len_max); - return M3UA_ERR_PARAM_FIELD_ERR; - } - } - - return 0; + return xua_dialect_check_all_ies_ext(dialect, xmc, msg_type, ies, xua, false); }
char *xua_msg_dump(const struct xua_msg *xua, const struct xua_dialect *dialect) diff --git a/src/xua_msg.h b/src/xua_msg.h index 3070435..6e36a7b 100644 --- a/src/xua_msg.h +++ b/src/xua_msg.h @@ -126,6 +126,9 @@ char *xua_hdr_dump(const struct xua_msg *xua, const struct xua_dialect *dialect); char *xua_msg_dump(const struct xua_msg *xua, const struct xua_dialect *dialect); int xua_dialect_check_all_ies(const struct xua_dialect *dialect, const struct xua_msg *xua); +int xua_dialect_check_all_ies_ext(const struct xua_dialect *dialect, const struct xua_msg_class *xmc, + uint8_t msg_type, const struct xua_msg_part_class *ies, + const struct xua_msg *xua, bool repeated_parts);
int xua_msg_event_map(const struct xua_msg *xua, const struct xua_msg_event_map *maps, diff --git a/src/xua_rkm.c b/src/xua_rkm.c index 92fbdac..6f2efc2 100644 --- a/src/xua_rkm.c +++ b/src/xua_rkm.c @@ -349,6 +349,7 @@ struct msgb *resp = m3ua_msgb_alloc(__func__); struct osmo_ss7_as *newly_assigned_as[MAX_NEW_AS]; unsigned int i, num_newly_assigned_as = 0; + int rc;
memset(newly_assigned_as, 0, sizeof(newly_assigned_as));
@@ -362,7 +363,17 @@ inner = xua_from_nested(part); if (!inner) { LOGPASP(asp, DLSS7, LOGL_NOTICE, "RKM: Unable to parse " - "nested IE for Routing Key\n"); + "nested IEs in Routing Key\n"); + /* FIXME: ERROR to peer */ + continue; + } + rc = xua_dialect_check_all_ies_ext(&xua_dialect_m3ua, &m3ua_msg_class_rkm, M3UA_RKM_REG_REQ, + m3ua_rkm_reg_req_routing_key_ies, inner, true); + if (rc > 0) { + LOGPASP(asp, DLSS7, LOGL_NOTICE, "RKM: Unable to parse " + "nested IEs in Routing Key\n"); + xua_msg_free(inner); + /* FIXME: ERROR to peer */ continue; } /* handle single registration and append result to @@ -502,6 +513,7 @@ { struct xua_msg_part *part; struct xua_msg *inner = NULL; + int rc;
llist_for_each_entry(part, &xua->headers, entry) { /* skip other IEs and/or short REG_RES IEs */ @@ -512,8 +524,22 @@ * registration result (we only support one AS per ASP * for now) */ inner = xua_from_nested(part); - if (!inner) + if (!inner) { + LOGPASP(asp, DLSS7, LOGL_NOTICE, "RKM: Unable to parse " + "nested IEs in Registration Result\n"); + /* FIXME: ERROR to peer */ continue; + } + + rc = xua_dialect_check_all_ies_ext(&xua_dialect_m3ua, &m3ua_msg_class_rkm, M3UA_RKM_REG_RSP, + m3ua_rkm_reg_rsp_registration_result_ies, inner, false); + if (rc > 0) { + LOGPASP(asp, DLSS7, LOGL_NOTICE, "RKM: Unable to parse " + "nested IEs in Registration Result\n"); + xua_msg_free(inner); + /* FIXME: ERROR to peer */ + continue; + }
handle_rkey_reg_resp(asp, inner); xua_msg_free(inner); @@ -526,13 +552,6 @@ { struct osmo_xlm_prim *oxp;
- if (!xua_msg_find_tag(inner, M3UA_IEI_DEREG_STATUS) || - !xua_msg_find_tag(inner, M3UA_IEI_ROUTE_CTX)) { - LOGPASP(asp, DLSS7, LOGL_NOTICE, "Missing Inner IE in DEREG RESP\n"); - /* FIXME: ERROR to peer */ - return -1; - } - oxp = xua_xlm_prim_alloc_m_rk_dereg_cfm(xua_msg_get_u32(inner, M3UA_IEI_ROUTE_CTX), xua_msg_get_u32(inner, M3UA_IEI_DEREG_STATUS));
@@ -551,6 +570,7 @@ { struct xua_msg_part *part; struct xua_msg *inner = NULL; + int rc;
llist_for_each_entry(part, &xua->headers, entry) { /* skip other IEs and/or short REG_RES IEs */ @@ -561,8 +581,22 @@ * registration result (we only support one AS per ASP * for now) */ inner = xua_from_nested(part); - if (!inner) + if (!inner) { + LOGPASP(asp, DLSS7, LOGL_NOTICE, "RKM: Unable to parse " + "nested IEs in Deregistration Result\n"); + /* FIXME: ERROR to peer */ continue; + } + + rc = xua_dialect_check_all_ies_ext(&xua_dialect_m3ua, &m3ua_msg_class_rkm, M3UA_RKM_DEREG_RSP, + m3ua_rkm_dereg_rsp_deregistration_result_ies, inner, false); + if (rc > 0) { + LOGPASP(asp, DLSS7, LOGL_NOTICE, "RKM: Unable to parse " + "nested IEs in Deregistration Result\n"); + xua_msg_free(inner); + /* FIXME: ERROR to peer */ + continue; + }
handle_rkey_dereg_resp(asp, inner); xua_msg_free(inner);