Implement sim auth resync

Related: OS#6345
Change-Id: I75413b0c4b491425c3b01d75fdd1674cf7f3bbde
This commit is contained in:
Pau Espin 2024-03-08 19:15:40 +01:00
parent 8ecd6e5618
commit a0dcef110c
6 changed files with 59 additions and 44 deletions

View File

@ -20,7 +20,7 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([code_change/3, terminate/2]).
-export([auth_request/3, auth_compl_request/2, session_termination_request/1]).
-export([auth_request/4, auth_compl_request/2, session_termination_request/1]).
-export([auth_response/2, auth_compl_response/2, session_termination_answer/2]).
-define(SERVER, ?MODULE).
@ -47,8 +47,8 @@ session_termination_answer(Imsi, Result) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Rx from emulated SWm wire:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
auth_request(Imsi, PdpTypeNr, Apn) ->
gen_server:cast(?SERVER, {epdg_auth_req, Imsi, PdpTypeNr, Apn}).
auth_request(Imsi, PdpTypeNr, Apn, EAP) ->
gen_server:cast(?SERVER, {epdg_auth_req, Imsi, PdpTypeNr, Apn, EAP}).
auth_compl_request(Imsi, Apn) ->
gen_server:cast(?SERVER, {epdg_auth_compl_req, Imsi, Apn}).
@ -56,9 +56,9 @@ auth_compl_request(Imsi, Apn) ->
session_termination_request(Imsi) ->
gen_server:cast(?SERVER, {str, Imsi}).
handle_cast({epdg_auth_req, Imsi, PdpTypeNr, Apn}, State0) ->
handle_cast({epdg_auth_req, Imsi, PdpTypeNr, Apn, EAP}, State0) ->
{Sess, State1} = find_or_new_swm_session(Imsi, State0),
aaa_ue_fsm:ev_swm_auth_req(Sess#swm_session.pid, {PdpTypeNr, Apn}),
aaa_ue_fsm:ev_swm_auth_req(Sess#swm_session.pid, {PdpTypeNr, Apn, EAP}),
{noreply, State1};
handle_cast({epdg_auth_compl_req, Imsi, Apn}, State) ->

View File

@ -50,7 +50,7 @@
%% gen_server Function Exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([code_change/3]).
-export([multimedia_auth_request/7]).
-export([multimedia_auth_request/6]).
-export([server_assignment_request/4]).
-export([test/0, test/1]).
@ -140,11 +140,11 @@ test() ->
test("001011234567890").
test(IMSI) ->
multimedia_auth_request(IMSI, 3, "EAP-AKA", 1, [], [], 33).
multimedia_auth_request(IMSI, 1, 3, "EAP-AKA", 33, []).
multimedia_auth_request(IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey, PdpTypeNr) ->
multimedia_auth_request(IMSI, RAT, NumAuthItems, AuthScheme, PdpTypeNr, AuthorizationOpt) ->
gen_server:call(?SERVER,
{mar, {IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey, PdpTypeNr}}).
{mar, {IMSI, RAT, NumAuthItems, AuthScheme, PdpTypeNr, AuthorizationOpt}}).
% APN is optional and should be []
server_assignment_request(IMSI, Type, APN, AgentInfoOpt) ->
gen_server:call(?SERVER,
@ -185,7 +185,7 @@ parse_saa(#'SAA'{'Experimental-Result' = [#{'Vendor-Code' := ?VENDOR_ID_3GPP, 'E
parse_saa(Saa) ->
{unknown_err, []}.
handle_call({mar, {IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey, PdpTypeNr}}, {Pid, _Tag} = _From, State) ->
handle_call({mar, {IMSI, RAT, NumAuthItems, AuthScheme, PdpTypeNr, AuthorizationOpt}}, {Pid, _Tag} = _From, State) ->
SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, origin_host, ?ENV_DEFAULT_ORIG_HOST)),
% RFC 4005 6.11.1 Framed-IP-Address AVP:
% "0xFFFFFFFE indicates that the NAS should select an address for the user
@ -217,8 +217,7 @@ handle_call({mar, {IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey, PdpT
'Auth-Session-State' = 1,
'SIP-Auth-Data-Item' = #'SIP-Auth-Data-Item'{
'SIP-Authentication-Scheme' = [AuthScheme],
'Confidentiality-Key' = CKey,
'Integrity-Key' = IntegrityKey,
'SIP-Authorization' = AuthorizationOpt,
'Framed-IP-Address' = IPv4Opt,
'Framed-IPv6-Prefix' = IPv6Opt
},

View File

@ -67,10 +67,10 @@ start_link(Imsi) ->
lager:info("ue_fsm start_link(~p)~n", [ServerName]),
gen_statem:start_link({local, ServerName}, ?MODULE, Imsi, [{debug, [trace]}]).
ev_swm_auth_req(Pid, {PdpTypeNr, Apn}) ->
ev_swm_auth_req(Pid, {PdpTypeNr, Apn, EAP}) ->
lager:info("ue_fsm ev_swm_auth_req~n", []),
try
gen_statem:call(Pid, {swm_auth_req, PdpTypeNr, Apn})
gen_statem:call(Pid, {swm_auth_req, PdpTypeNr, Apn, EAP})
catch
exit:Err ->
{error, Err}
@ -153,15 +153,16 @@ terminate(Reason, State, Data) ->
state_new(enter, _OldState, Data) ->
{keep_state, Data};
state_new({call, From}, {swm_auth_req, PdpTypeNr, Apn}, Data) ->
lager:info("ue_fsm state_new event=swm_auth_req {~p, ~p}, ~p~n", [PdpTypeNr, Apn, Data]),
% request the diameter code for a tuple
CKey = [],
IntegrityKey = [],
case aaa_diameter_swx:multimedia_auth_request(Data#ue_fsm_data.imsi, 1, "EAP-AKA", 1, CKey, IntegrityKey, PdpTypeNr) of
ok -> {next_state, state_wait_swx_maa, Data, [{reply,From,ok}]};
{error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]}
end;
state_new({call, From}, {swm_auth_req, PdpTypeNr, Apn, EAP}, Data) ->
lager:info("ue_fsm state_new event=swm_auth_req {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
case maps:find(authorization, EAP) of
{ok, Authorization} when is_binary(Authorization) -> Authorization;
error -> Authorization = []
end,
case aaa_diameter_swx:multimedia_auth_request(Data#ue_fsm_data.imsi, 1, 1, "EAP-AKA", PdpTypeNr, Authorization) of
ok -> {next_state, state_wait_swx_maa, Data, [{reply,From,ok}]};
{error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]}
end;
state_new({call, From}, {swm_auth_compl, Apn}, Data) ->
lager:info("ue_fsm state_new event=swm_auth_compl, ~p~n", [Data]),
@ -251,8 +252,8 @@ state_authenticated({call, {Pid, _Tag} = From}, rx_s6b_str, Data) ->
end
end;
state_authenticated({call, _From}, {swm_auth_req, PdpTypeNr, Apn}, Data) ->
lager:info("ue_fsm state_authenticated event=swm_auth_req {~p, ~p}, ~p~n", [PdpTypeNr, Apn, Data]),
state_authenticated({call, _From}, {swm_auth_req, PdpTypeNr, Apn, EAP}, Data) ->
lager:info("ue_fsm state_authenticated event=swm_auth_req {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
{next_state, state_new, Data, [postpone]};
state_authenticated({call, From}, Ev, Data) ->

View File

@ -19,7 +19,7 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([code_change/3, terminate/2]).
-export([auth_request/3, auth_compl_request/2, session_termination_request/1]).
-export([auth_request/4, auth_compl_request/2, session_termination_request/1]).
-export([auth_response/2, auth_compl_response/2, session_termination_answer/2]).
-define(SERVER, ?MODULE).
@ -33,13 +33,14 @@ init([]) ->
{ok, #swm_state{}}.
auth_request(Imsi, PdpTypeNr, Apn) ->
%% Swm Diameter message Diameter-EAP-Request, 3GPP TS 29.273 Table 7.1.2.1.1
auth_request(Imsi, PdpTypeNr, Apn, EAP) ->
% In Diameter we use Imsi as strings, as done by diameter module.
ImsiStr = binary_to_list(Imsi),
% epdg_auth_req: Swm Diameter message Diameter-EAP-Request 3GPP TS 29.273 7.2.2.1.1
% PdpTypeNr: SWm Diameter AVP "UE-Local-IP-Address"
% Apn: SWm Diameter AVP "Service-Selection"
Result = gen_server:call(?SERVER, {epdg_auth_req, ImsiStr, PdpTypeNr, Apn}),
% EAP: SWm Diameter AVP EAP-Payload
Result = gen_server:call(?SERVER, {epdg_auth_req, ImsiStr, PdpTypeNr, Apn, EAP}),
case Result of
{ok, _AuthTuples} ->
epdg_ue_fsm:received_swm_auth_response(self(), Result),
@ -71,10 +72,10 @@ session_termination_request(Imsi) ->
_ -> Result
end.
handle_call({epdg_auth_req, Imsi, PdpTypeNr, Apn}, {Pid, _Tag} = _From, State0) ->
handle_call({epdg_auth_req, Imsi, PdpTypeNr, Apn, EAP}, {Pid, _Tag} = _From, State0) ->
% we yet don't implement the Diameter SWm interface on the wire, we process the call internally:
{_Sess, State1} = find_or_new_swm_session(Imsi, Pid, State0),
ok = aaa_diameter_swm:auth_request(Imsi, PdpTypeNr, Apn),
ok = aaa_diameter_swm:auth_request(Imsi, PdpTypeNr, Apn, EAP),
{reply, ok, State1};
handle_call({epdg_auth_compl_req, Imsi, Apn}, _From, State) ->

View File

@ -81,10 +81,10 @@ stop(SrvRef) ->
{error, Err}
end.
auth_request(Pid, {PdpTypeNr, Apn}) ->
auth_request(Pid, {PdpTypeNr, Apn, EAP}) ->
lager:info("ue_fsm auth_request~n", []),
try
gen_statem:call(Pid, {auth_request, PdpTypeNr, Apn})
gen_statem:call(Pid, {auth_request, PdpTypeNr, Apn, EAP})
catch
exit:Err ->
{error, Err}
@ -176,8 +176,8 @@ received_gtpc_delete_bearer_request(Pid) ->
%% Internal helpers
%% ------------------------------------------------------------------
ev_handle({call, From}, {auth_request, PdpTypeNr, Apn}, Data) ->
case epdg_diameter_swm:auth_request(Data#ue_fsm_data.imsi, PdpTypeNr, Apn) of
ev_handle({call, From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) ->
case epdg_diameter_swm:auth_request(Data#ue_fsm_data.imsi, PdpTypeNr, Apn, EAP) of
ok -> {next_state, state_wait_auth_resp, Data, [{reply,From,ok}]};
{error, Err} -> {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]}
end.
@ -205,8 +205,8 @@ terminate(Reason, State, Data) ->
state_new(enter, _OldState, Data) ->
{keep_state, Data};
state_new({call, _From} = EvType, {auth_request, PdpTypeNr, Apn} = EvContent, Data) ->
lager:info("ue_fsm state_new event=auth_request {~p, ~p}, ~p~n", [PdpTypeNr, Apn, Data]),
state_new({call, _From} = EvType, {auth_request, PdpTypeNr, Apn, EAP} = EvContent, Data) ->
lager:info("ue_fsm state_new event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
ev_handle(EvType, EvContent, Data);
state_new({call, From}, purge_ms_request, Data) ->
@ -233,8 +233,8 @@ state_wait_auth_resp({call, From}, {received_swm_auth_response, Result}, Data) -
state_authenticating(enter, _OldState, Data) ->
{keep_state, Data};
state_authenticating({call, _From} = EvType, {auth_request, PdpTypeNr, Apn} = EvContent, Data) ->
lager:info("ue_fsm state_authenticating event=auth_request {~p, ~p}, ~p~n", [PdpTypeNr, Apn, Data]),
state_authenticating({call, _From} = EvType, {auth_request, PdpTypeNr, Apn, EAP} = EvContent, Data) ->
lager:info("ue_fsm state_authenticating event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
ev_handle(EvType, EvContent, Data);
state_authenticating({call, From}, lu_request, Data) ->
@ -270,8 +270,8 @@ state_authenticating({call, From}, {received_swm_auth_compl_response, Result}, D
state_authenticated(enter, _OldState, Data) ->
{keep_state, Data};
state_authenticated({call, _From}, {auth_request, PdpTypeNr, Apn}, Data) ->
lager:info("ue_fsm state_authenticated event=auth_request {~p, ~p}, ~p~n", [PdpTypeNr, Apn, Data]),
state_authenticated({call, _From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) ->
lager:info("ue_fsm state_authenticated event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
{next_state, state_new, Data, [postpone]};
state_authenticated({call, From}, {tunnel_request, PCO}, Data) ->
@ -338,8 +338,8 @@ state_wait_create_session_resp(state_timeout, create_session_timeout, Data) ->
state_active(enter, _OldState, Data) ->
{keep_state, Data};
state_active({call, _From}, {auth_request, PdpTypeNr, Apn}, Data) ->
lager:info("ue_fsm state_active event=auth_request {~p, ~p}, ~p~n", [PdpTypeNr, Apn, Data]),
state_active({call, _From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) ->
lager:info("ue_fsm state_active event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
gtp_u_tun:delete_pdp_context(Data#ue_fsm_data.tun_pdp_ctx),
Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined},
{next_state, state_new, Data1, [postpone]};

View File

@ -267,6 +267,19 @@ cancel_location_request(Imsi) ->
%% Internal Function Definitions
%% ------------------------------------------------------------------
%% Put params transparent to ePDG in a container, they are for AAA Server (RFC7296):
parse_eap(GsupMsgRx = #{message_type := send_auth_info_req}) ->
RandRes = maps:find(rand, GsupMsgRx),
AutsRes = maps:find(auts, GsupMsgRx),
case {RandRes, AutsRes} of
{{ok, <<Rand:16/binary>>}, {ok, <<Auts:14/binary>>}} ->
% Authorization: SWx Diameter AVP SIP-Authorization for resynchronisation of the Simcard
EAP = #{authorization => <<Rand:16/binary, Auts:14/binary>>};
_ ->
EAP = #{}
end,
EAP.
% Rx send auth info / requesting authentication tuples
rx_gsup(Socket, GsupMsgRx = #{message_type := send_auth_info_req, imsi := Imsi}, State) ->
case maps:find(pdp_info_list, GsupMsgRx) of
@ -281,11 +294,12 @@ rx_gsup(Socket, GsupMsgRx = #{message_type := send_auth_info_req, imsi := Imsi},
PdpTypeNr = ?GTP_PDP_ADDR_TYPE_NR_IPv4,
Apn = "*"
end,
EAP = parse_eap(GsupMsgRx),
case epdg_ue_fsm:get_pid_by_imsi(Imsi) of
undefined -> {ok, Pid} = epdg_ue_fsm:start(Imsi);
Pid -> Pid
end,
case epdg_ue_fsm:auth_request(Pid, {PdpTypeNr, Apn}) of
case epdg_ue_fsm:auth_request(Pid, {PdpTypeNr, Apn, EAP}) of
ok -> ok;
{error, Err} ->
lager:error("Auth Req for Imsi ~p failed: ~p~n", [Imsi, Err]),