In InitialUEMessage, send a NAS message with a message type
other than Registration Request, Deregistration Request, or Service Request,
the following messages from UE will not be accepted.
We found this issue in not only the initial state but multiple states.
We believe if an attacker has the ability to inject a NAS message to the core,
it can perform a DoS attack on the victim UE.
So, I've fixed that The MME/AMF deletes MME_UE_S1AP_ID/AMF_UE_NGAP_ID,
and will not accept any following messages from the UE.
The AMF will crash on the following locations when it receives a sequence
of NAS messages from a UE.
- ogs_nas_encrypt: Assertion `pkbuf->len' failed. (../lib/nas/common/security.c:86)
- gmm_state_authentication: Assertion `r != OGS_ERROR' failed. (../src/amf/gmm-sm.c:1561)
Besides the crashes found above, an incorrect protocol transition
is identified in Open5GS. Without any Registration/Attach Request message,
when the Identity Response message sent, the Core Network responds
with an Authentication Request message. According to the standard,
only the Registration/Attach Request message can start a state transition
from the 5GMM/EMM-DEREGISTERED state to the 5GMM/EMM-COMMON-PROCEDURE-INITIATED.
So I've modified the relevant code to address these issues.
First of all, it crashes when creating a Dedicated Bearer
on the default Session that is created for the first time.
This behavior should be possible, so the related ASSERT is removed.
Next, the InitialContextRequest is modified
during the Attach Request to include the first Bearer.
Finally, there was an issue where trying to create a Dedicated Bearer
with SGsAP enabled resulted in an InitialContextSetupRequest message
with a PTI of zero. This is because MME initializes the PTI to 0
upon receiving the Create Bearer Request while processing SGsAP.
All of these issues has been fixed.
1. According to ETSI TS 129 118 4.1, if the Network Access Mode (NAM) is set
to "Packet only," no SGs association should be established.
2. If the NAM is set to "Packet and Circuit," and the SGs association is
rejected by the CS core, this rejection should only impact
the SGs association itself and not result in a UE attach rejection
for a UE with a valid HSS account.
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
Assume the UE has Attached, the session has been created,
and is in the IDLE state with the UEContextRelease process.
This could result in the following call flow.
1. TAU request without Integrity Protected
2. Authentication request/response
3. Security-mode command/complete
MME can be performed simultaneously by the HSS(S6A) and UE(S1AP).
Update-Location-Request
Service request
Service reject
Delete Session Request
Delete Session Response
Update-Location-Answer
UEContextReleaseCommand for Service reject
TAU reject
UEContextReleaseCommand for TAU reject
UEContextReleaseComplete
UEContextReleaseComplete
MME crashes when UE sends a service request(S1AP) during ULR/ULA(S6A) with HSS,
which has been fixed.
Transaction Identity doesn't map 1-to-1 with Procedure Transaction
Identity: The value ranges change, and PTI cannot use value 0 8which
means unused).
Hence, for now let's simply set the PTI to a valid default value instead
of asserting during mme_sess_add:
Assertion `pti != OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED'
Related: https://github.com/open5gs/open5gs/issues/3020
1. HandoverRequired
2. HandoverRequest
3. HandoverFailure
4. UEContextReleaseCommand
5. HandoverPreparationFailure
If UEContextReleaseComplete is not received,
the Source-UE will have the Target-UE.
6. HandoverRequired
There may be cases where the Source UE has a Target UE
from a previous HandoverRequired process. In this case,
it is recommended to force the deletion of the Target UE information
when receiving a new HandoverRequired.
7. HandoverRequest
8. HandoverFailure
9. UEContextReleaseCommand
10. UEContextReleaseComplete
11. HandoverPreparationFailure
... Crashed ...
APER encoding fails when using the asn_uint642INTEGER function on a 32-bit machine as shown below.
```C
asn_uint642INTEGER(AMF_UE_NGAP_ID, 0xffffffff);
...
aper_encode_to_buffer(...)
```
INTEGER APER encode/decode functions seem to be operating internally with long variables instead of intmax_t.
That is probably the reason of the failure.
@v0-e fixed this issues in the mouse07410/asn1c pull request.
https://github.com/mouse07410/asn1c/pull/176https://github.com/mouse07410/asn1c/pull/177
When there is no MME-UE Context, going to cleanup without setting
s6a_message could cause a segmentation fault.
We fixed the problem by moving the location of setting s6a_message
to before cleanup.
Problems with Purge-UE-Request/Answer can occur in the following situations
1. Attach Request
2. Authentication request
3. Authentication reject
4. UEContextReleaseCommand
5. UEContextReleaseComplete
6. Purge-UE-Request
7. Attach Request
8. Purge-UE-Answer
9. (UE Context Remove)
To resolve this issue, we have changed to delete the UE-Context
via mme_ue_remove() immediately upon receiving UEContextReleaseComplete()
without calling mme_s6a_send_pur().
1. Reachable assertion in ogs_nas_5gmm_decode
Location: lib/nas/5gs/decoder.c:4445
```c
int ogs_nas_5gmm_decode(ogs_nas_5gs_message_t *message, ogs_pkbuf_t *pkbuf)
{
int size = 0;
int decoded = 0;
ogs_assert(pkbuf);
ogs_assert(pkbuf->data);
ogs_assert(pkbuf->len);
```
When a NAS payload is received over `src/amf/context.c:1675`NGAP that has no data, the ogs_assert(pkbuf->len) assertion will be triggered.
2.Reachable assertion in ogs_nas_emm_decode
```
int ogs_nas_emm_decode(ogs_nas_eps_message_t *message, ogs_pkbuf_t *pkbuf)
{
int size = 0;
int decoded = 0;
ogs_assert(pkbuf);
ogs_assert(pkbuf->data);
ogs_assert(pkbuf->len);
```
Nearly identical to (1), but for LTE.
3. Reachable assertion in nas_eps_send_emm_to_esm
```
int nas_eps_send_emm_to_esm(mme_ue_t *mme_ue,
ogs_nas_esm_message_container_t *esm_message_container)
{
int rv;
ogs_pkbuf_t *esmbuf = NULL;
if (!mme_ue_cycle(mme_ue)) {
ogs_error("UE(mme-ue) context has already been removed");
return OGS_NOTFOUND;
}
ogs_assert(esm_message_container);
ogs_assert(esm_message_container->length);
```
The ESM message payload may be 0-length, as the length is determined by a field in the NAS payload (which can be chosen arbitrarily by an attacker). This leads to the length assertion above being triggered.
5. Reachable assertion and incorrect hash calculation in ogs_kdf_hash_mme
```
void ogs_kdf_hash_mme(const uint8_t *message, uint8_t message_len, uint8_t *hash_mme)
{
uint8_t key[32];
uint8_t output[OGS_SHA256_DIGEST_SIZE];
ogs_assert(message);
ogs_assert(message_len);
ogs_assert(hash_mme);
memset(key, 0, 32);
ogs_hmac_sha256(key, 32, message, message_len,
output, OGS_SHA256_DIGEST_SIZE);
memcpy(hash_mme, output+24, OGS_HASH_MME_LEN);
}
```
When handling NAS attach requests or TAU requests, the ogs_kdf_hash_mme function is passed the NAS payload. However, the length field is represented as an unsigned 8-bit integer, which the passed length of the packet may overflow. This leads to the passed value being truncated.
When the passed value is a multiple of 256, the above assertion (ogs_assert(message_len)) is triggered. Otherwise, the hash is computed on only the first n bits of the message (where n = actual_message_len % 256).
Because a race condition can occur between S6A Diameter and S1AP message,
the following error handling code has been added.
1. InitialUEMessage + Attach Request + PDN Connectivity request
2. Authentication-Information-Request/Authentication-Information-Answer
3. Authentication Request/Response
4. Security-mode command/complete
5. Update-Location-Request/Update-Location-Answer
6. Detach request/accept
In the ULR/ULA process in step 6, the PDN Connectivity request is
pushed to the queue as an ESM_MESSAGE because the NAS-Type is still
an Attach Request.
See the code below in 'mme-s6a-handler.c' for where the queue is pushed.
if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) {
rv = nas_eps_send_emm_to_esm(mme_ue,
&mme_ue->pdn_connectivity_request);
if (rv != OGS_OK) {
ogs_error("nas_eps_send_emm_to_esm() failed");
return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED;
}
} else if (mme_ue->nas_eps.type == MME_EPS_TYPE_TAU_REQUEST) {
r = nas_eps_send_tau_accept(mme_ue,
S1AP_ProcedureCode_id_InitialContextSetup);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
ogs_error("Invalid Type[%d]", mme_ue->nas_eps.type);
return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED;
}
If you perform step 7 Detach request/accept here,
the NAS-Type becomes Detach Request and the EMM state changes
to emm_state_de_registered().
Since the PDN, which is an ESM message that was previously queued,
should not be processed in de_registered, the message is ignored
through error handling below.
Otherwise, MME will crash because there is no active bearer
in the initial_context_setup_request build process.
See the code below in 's1ap-build.c' for where the crash occurs.
ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
...
if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) {
} else if (OGS_FSM_CHECK(&bearer->sm, esm_state_inactive)) {
ogs_warn("No active EPS bearer [%d]", bearer->ebi);
ogs_warn(" IMSI[%s] NAS-EPS Type[%d] "
"ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
mme_ue->imsi_bcd, mme_ue->nas_eps.type,
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
continue;
}
...
}
}
A race condition can occur in the following situations.
In conclusion, we can use this situation to determine
whether or not the UE Context has been removed and avoiding a crash.
For example, suppose a UE Context is removed in the followings.
1. Attach Request
2. Authentication-Information-Request
3. Authentication-Information-Answer
4. Authentication Request
5. Authentication Response(MAC Failed)
6. Authentication Reject
7. UEContextReleaseCommand
8. UEContextReleaseComplete
The MME then sends a Purge-UE-request to the HSS and deletes
the UE context as soon as it receives a Purge-UE-Answer.
Suppose an Attach Request is received from the same UE
between Purge-UE-Request/Answer, then the MME and HSS start
the Authentication-Information-Request/Answer process.
This can lead to the following situations.
1. Purge-UE-Request
2. Attach Request
3. Authentication-Information-Request
4. Purge-UE-Answer
5. [UE Context Removed]
6. Authentication-Information-Answer
Since the UE Context has already been deleted
when the Authentication-Information-Answer is received,
it cannot be processed properly.
Therefore, mme_ue_cycle() is used to check
whether the UE Context has been deleted and
decide whether to process or
ignore the Authentication-Information-Answer as shown below.
In an Inter-RAT setup a UE could perform a TAU coming from a 2G/3G network.
In that case the UE/MS is unknown to the MME and it should request the
SGSN context (MM, PDP) from the old SGSN. This is done through the following
GTPv1C message exchange on the Gn interface of SGSN and MME:
SGSN <- MME: SGSN Context Request
SGSN -> MME: SGSN Context Response
SGSN <- MME: SGSN Context Acknowledge
Diagram with full set of steps can be found at 3GPP TS 23.401 D.3.6.
This commit doesn't aim to be a complete implementation of the mentioned
procedure, since it's quite a complex one, with lots of fields and logic
required. This so far only implements in general the minimally
successful case by filling as much as possible the required set of
fields.
This will allow for a base onto which do incremental improvements and
fixes while testing against UEs and SGSNs (such as osmo-sgsn, which
doesn't yet support this procedure but will potentially earn it soon).
The reverse direction, aka UE issuing cell reselection 4G->2G was
already implemented (same as here, initial non-complete implementation)
in open5gs-mmed in commit 3d693da73e.
Related: https://osmocom.org/issues/6294
Within the PathSwitchRequest packet,
the E-RABToBeSwitchedDLList has two bearers.
If the E-RAB-ID of both bearers is 5, the MME's list memory is destroyed
and the MME crashes. To fix this issue, we modified the code so that
the MME can work correctly with invalid S1AP messages.
This will be useful for other procedures where only the RAI is known,
but not the specific CI. This is the case of idle mobility from Gb or Iu
to EUTRAN, where MME needs to request contexts based on the RAI mapped
in the GUTI obtained from the UE during TAU.
This also makes the config more resilient in RIM scenario, where an SGSN
can be picked now even if CI doesn't match, instead of failing or faling
back to the default route SGSN.
Both types are defined under lib/proto/type.h, and the conversion
function is used in several different protocols, so let's better move it
to generic lib/proto/conv.h and remove the "gtp2" prefix.
The assert is checking for sess->session->name, but afterwards there's a
check to skip ses->session not being null, which means the assert can
crash while dereferencing sess->session.
In an Inter-RAT setup a UE could perform a RAU coming from a 4G network.
In that case the UE/MS is unknown to the SGSN and it should request the
SGSN context (MM, PDP) from the MME. This is done through the following
GTPv1C message exchange on the Gn interface of SGSN and MME:
SGSN -> MME: SGSN Context Request
SGSN <- MME: SGSN Context Response
SGSN -> MME: SGSN Context Acknowledge
This commit doesn't aim to be a complete implementation of the mentioned
procedure, since it's quite a complex one, with lots of fields and logic
required. This so far only implements in general the minimally
successful case by filling as much as possible the required set of
fields.
This will allow for a base onto which do incremental improvements and
fixes while testing against UEs and SGSNs (such as osmo-sgsn, which
doesn't yet support this procedure but will potentially earn it soon).
This commit doesn't implement the reverse direction, aka UE issuing cell
reselection 2G->4G. Initial support for this scenario will hopefully be
added soon as a follow-up patch, similar to this one.
Related: https://osmocom.org/issues/6294
In an Inter-RAT setup a UE could perform a RAU coming from a 4G network.
In that case the UE/MS is unknown to the SGSN and it should request the
SGSN context (MM, PDP) from the MME. This is done through the following
GTPv1C message exchange on the Gn interface of SGSN and MME:
SGSN -> MME: SGSN Context Request
SGSN <- MME: SGSN Context Response
SGSN -> MME: SGSN Context Acknowledge
This commit doesn't aim to be a complete implementation of the mentioned
procedure, since it's quite a complex one, with lots of fields and logic
required. This so far only implements in general the minimally
successful case by filling as much as possible the required set of
fields.
This will allow for a base onto which do incremental improvements and
fixes while testing against UEs and SGSNs (such as osmo-sgsn, which
doesn't yet support this procedure but will potentially earn it soon).
This commit doesn't implement the reverse direction, aka UE issuing cell
reselection 2G->4G. Initial support for this scenario will hopefully be
added soon as a follow-up patch, similar to this one.
Related: https://osmocom.org/issues/6294
This information will be required by the Gn interface in MME when
answering an SGSN with an "SGSN Context Response" message during MS cell
reselection EUTRAN->GERAN.
* [AMF/MME] UEContextReleaseCommand in Integrity (#2786)
Modified not to send UEContextReleaseCommand in Integrity Unprotected
NAS message such like Registration or Service request.
* [AMF/MME] UEContextReleaseCommand after Interity Protected (#2786)
Modified not to send UEContextReleaseCommand in Integrity Unprotected
NAS message such like Registration or Service request.
Allow network operators to omit the time zone in the 4G EMM Information
and 5G Configuration Update. This is useful for better compatibility
with some UEs.
The parameter is optional according to:
* 4G: 3GPP TS 24.301 Table 8.2.13.1
* 5G: 3GPP TS 24.501 Table 8.2.19.1.1
amf_ue->mac_failed flag to be cleared during security mode procedure but it was not.
At this point, the only way to cleare the amf_ue->mac_failed flag is by UE Context Release.
But I'd like to connect UEs as fast as possible without UE Context Release.