Bug #4830
openLU reject when no authentication data in HLR but "authentication optional"
Added by laforge almost 4 years ago. Updated almost 2 years ago.
0%
Updated by laforge almost 4 years ago
- Category set to VLR
- Assignee set to neels
- Priority changed from Normal to High
I have a network configured as follows in the msc:
network network country code 901 mobile network code 70 short name OsmoMSC long name OsmoMSC encryption a5 0 1 3 encryption uea 1 2 authentication optional rrlp mode none mm info 1 msc mncc guard-timeout 180 ncss guard-timeout 30 assign-tmsi cs7-instance-a 0 cs7-instance-iu 0 auth-tuple-max-reuse-count 3 auth-tuple-reuse-on-error 1 mgw local-port 2728 mgw remote-ip 127.0.0.1 mgw remote-port 2427
So A5/0 is permitted, and authentication is entirely optional.
But what seems to happen is that the MSC asks the HLR for authentication data. However, the HLR doesn't have any authentication data for that subscriber (it only knows the IMSI, but no key material):
<0012> hlr.c:314 GSUP 6: MSC-00-00-00-00-00-00: IMSI-001010000000001 OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: IMSI unknown in HLR: IMSI known, but has no auth data; Returning slightly inaccurate cause 'IMSI Unknown' via GSUP
The MSC then subsquently rejects the LU:
<0002> gsm_04_08.c:347 msc_a(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91be0]{MSC_A_ST_VALIDATE_L3}: LOCATION UPDATING REQUEST: MI=IMSI-001010000000001 LU-type=NORMAL <0002> gsm_04_08.c:390 msc_a(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91be0]{MSC_A_ST_VALIDATE_L3}: USIM: old LAI: 001-01-0 <000e> fsm.c:461 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_IDLE}: Allocated <000e> fsm.c:491 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_IDLE}: is child of msc_a(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91be0] <000e> vlr_lu_fsm.c:1523 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth+Ciph <000e> vlr_lu_fsm.c:1529 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA <000e> vlr.c:435 set IMSI on subscriber; IMSI=001010000000001 id=1010000000001 <000e> vlr.c:386 New subscr, IMSI: 001010000000001 <000e> vlr_lu_fsm.c:924 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_IDLE}: vlr_loc_upd_node1_pre() <000e> vlr_lu_fsm.c:901 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_IDLE}: vlr_loc_upd_node1() <000e> vlr_lu_fsm.c:908 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_IDLE}: State change to VLR_ULA_S_WAIT_AUTH (T0, 30s) <000e> fsm.c:461 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH}: Allocated <000e> fsm.c:491 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10] <000e> vlr_auth_fsm.c:628 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START <000e> vlr_auth_fsm.c:318 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH}: State change to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI (T0, 30s) <000e> vlr.c:767 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK <000e> vlr_auth_fsm.c:339 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 2: IMSI unknown in HLR <000e> vlr_auth_fsm.c:244 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result IMSI unknown in HLR <000e> vlr_auth_fsm.c:250 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: State change to VLR_SUB_AS_AUTH_FAILED (no timeout) <000e> vlr_auth_fsm.c:253 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) <000e> vlr_auth_fsm.c:253 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10] <000e> vlr_auth_fsm.c:253 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_AUTH_FAILED}: Freeing instance <000e> fsm.c:573 VLR_Authenticate(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae92020]{VLR_SUB_AS_AUTH_FAILED}: Deallocated <000e> vlr_auth_fsm.c:253 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES <0002> gsm_04_08.c:108 msc_a(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91be0]{MSC_A_ST_AUTH_CIPH}: LOCATION UPDATING REJECT <000e> vlr_lu_fsm.c:741 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_WAIT_AUTH}: State change to VLR_ULA_S_DONE (no timeout) <000e> msc_a.c:836 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT) <000e> msc_a.c:836 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_DONE}: Removing from parent msc_a(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91be0] <000e> vlr_lu_fsm.c:1448 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT <000e> msc_a.c:836 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_DONE}: Freeing instance <000e> fsm.c:573 vlr_lu_fsm(IMSI-001010000000001:GERAN-A-6:LU)[0x5652eae91d10]{VLR_ULA_S_DONE}: Deallocated <000e> vlr.c:306 freeing VLR subscr IMSI-001010000000001 (max total use count was 4)
I think this is a perfectly valid configuration for people who don't have the key material for their SIM cards. They identify the subscriber via IMSI but don't cryptographically authenticate.
Is this not how it's supposed to work? If we have a bug, we should certainly have a related TTCN3 test...
Updated by neels almost 4 years ago
Taking a look:
The MSC part invokes the VLR part and passes in flags whether auth and ciph are required.
For LU:
vlr_loc_update(authentication_required = is_utran || net->authentication_required, ciphering_required = is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01)
So as soon as any A5 besides A5/0 (==0x01) is enabled, we pass in
ciphering_required = true, which also implies authentication_required = true.
For the other Complete Layer 3 it's the exact same thing, just via arguments to vlr_proc_acc_req().
So I guess instead of just the flag, the VLR should get the full encryption
mask and decide whether to do auth or not depending on the HLR's response.
That should be relatively trivial to implement, but then again not so trivial
since it affects the inner workings of the VLR FSMs.
Updated by laforge almost 4 years ago
On Tue, Oct 27, 2020 at 02:46:26PM +0000, neels [REDMINE] wrote:
The MSC part invokes the VLR part and passes in flags whether auth and ciph are required.
For LU:> vlr_loc_update(authentication_required = is_utran || net->authentication_required, > ciphering_required = is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01) >So as soon as any A5 besides A5/0 (==0x01) is enabled, we pass in
ciphering_required = true, which also implies authentication_required = true.
interesting, and - of course - a bug. Just because A5/1 or A%/3 are supported in the
network doesn't mean it is mandatory. Mandatory would only be in case no A5/0 is allowed.
So I guess instead of just the flag, the VLR should get the full encryption
mask and decide whether to do auth or not depending on the HLR's response.
looks reasonable.
That should be relatively trivial to implement, but then again not so trivial
since it affects the inner workings of the VLR FSMs.
But I guess we should have pretty good test coverage with the unit tests and the TTCN3
tests, so I'd think if something breaks we should see it in the tests and not in the field.
Updated by neels almost 2 years ago
It's been a while. I took a look at the current status. A patch from lynxis added this function:
bool msc_a_require_ciphering(const struct msc_a *msc_a) { struct gsm_network *net = msc_a_net(msc_a); bool is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU); if (is_utran) return net->uea_encryption_mask > (1 << OSMO_UTRAN_UEA0); else return net->a5_encryption_mask > 0x1; }
(2c5e46104e2fe718e6e68739ef70c4f8b1a586fe)
The signature of vlr_loc_update() is still
... bool authentication_required, bool ciphering_required, ...
This looks like osmo-msc can still not permit UEA0 when any UEA > 0 is also present in the config.
I.e. when any encryption is allowed in the config, then we still also require to use encryption.
Updated by neels almost 2 years ago
- Status changed from New to In Progress
Working with osmo-msc's auth and ciph code, I noticed that we don't have an 'authentication never' option.
I think users would expect that with 'authentication optional' osmo-msc would opt for the most secure way, meaning that when the HLR has auth info for the subscriber, we would do auth. Instead, for 'authentication optional', we do not even ask the HLR for auth info (only if ciphering is enabled).
Behavior of 'authentication optional', for brevity I list only a5 0 and 3: a5 0 a5 0 3 a5 3 Current behavior No auth, Require auth Require auth Do not request and do ciph and do ciph auth tuples from HLR Want behavior Ask auth tuples from Ask auth tuples from Require auth HLR, if present do auth. HLR, if present do auth and do ciph No ciph. and ciph (2) (1)
(1) is probably the minimal fix for this issue. It changes osmo-msc's behavior only for the case of fallback from auth+a5/3 to no-auth,no-ciph.
I am wondering if (2) should also be changed (fixed) so that osmo-msc always asks auth tuples from the HLR. Only consider no-auth when there are no auth tuples in the HLR, i.e. after an actual GSUP SAI NACK response. It seems logical, but not sure if we should change the current behavior.