pespin has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/36217?usp=email )
Change subject: Implement sim auth resync ......................................................................
Implement sim auth resync
Related: OS#6345 Change-Id: I75413b0c4b491425c3b01d75fdd1674cf7f3bbde --- M src/aaa_diameter_swm.erl M src/aaa_diameter_swx.erl M src/aaa_ue_fsm.erl M src/epdg_diameter_swm.erl M src/epdg_ue_fsm.erl M src/gsup_server.erl 6 files changed, 69 insertions(+), 44 deletions(-)
Approvals: pespin: Looks good to me, approved; Verified Jenkins Builder: Verified
diff --git a/src/aaa_diameter_swm.erl b/src/aaa_diameter_swm.erl index 0e3fa45..5050ffb 100644 --- a/src/aaa_diameter_swm.erl +++ b/src/aaa_diameter_swm.erl @@ -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 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 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 @@ 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) -> diff --git a/src/aaa_diameter_swx.erl b/src/aaa_diameter_swx.erl index 72a360e..a4cb1d8 100644 --- a/src/aaa_diameter_swx.erl +++ b/src/aaa_diameter_swx.erl @@ -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("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) -> {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 @@ '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 }, diff --git a/src/aaa_ue_fsm.erl b/src/aaa_ue_fsm.erl index f06b326..5a6e847 100644 --- a/src/aaa_ue_fsm.erl +++ b/src/aaa_ue_fsm.erl @@ -67,10 +67,10 @@ 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 @@ 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 @@ 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) -> diff --git a/src/epdg_diameter_swm.erl b/src/epdg_diameter_swm.erl index 54626cf..c2babe3 100644 --- a/src/epdg_diameter_swm.erl +++ b/src/epdg_diameter_swm.erl @@ -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 @@ {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 @@ _ -> 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) -> diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl index fc3a7e9..dbee78a 100644 --- a/src/epdg_ue_fsm.erl +++ b/src/epdg_ue_fsm.erl @@ -81,10 +81,10 @@ {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 @@ %% 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 @@ 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_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_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_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]}; diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 0ef7ae7..1e11c3e 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -267,6 +267,19 @@ %% 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 @@ 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]),