epdg: Introduce test TC_authinfo_MAA_unknown_user

Related: OS#6391
Change-Id: Ie4d9d019ed56401e7e19197b4a777a1e6a55e7ee
diff --git a/epdg/EPDG_Tests.ttcn b/epdg/EPDG_Tests.ttcn
index 15d4341..45d7a1d 100644
--- a/epdg/EPDG_Tests.ttcn
+++ b/epdg/EPDG_Tests.ttcn
@@ -19,6 +19,7 @@
 import from DIAMETER_Types all;
 import from DIAMETER_Templates all;
 import from DIAMETER_rfc4004_Templates all;
+import from DIAMETER_ts29_272_Templates all;
 import from DIAMETER_ts29_273_Templates all;
 import from DIAMETER_Emulation all;
 
@@ -381,26 +382,50 @@
 	return hex2str(g_pars.imsi) & "@" & mp_s6b_nai_realm;
 }
 
-/* Diameter SWx MAR + MAA. */
-private altstep as_DIA_SWx_MA_success() runs on EPDG_ConnHdlr {
-	var PDU_DIAMETER rx_dia;
+private function f_DIA_SWx_tx_MAA_success(PDU_DIAMETER rx_mar) runs on EPDG_ConnHdlr {
 	var template (omit) AVP avp;
 	var octetstring sess_id;
 	var template (value) GenericAVP sip_auth_data_item;
+
+	avp := f_DIAMETER_get_avp(rx_mar, c_AVP_Code_BASE_NONE_Session_Id);
+	sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+	sip_auth_data_item := ts_AVP_3GPP_SIPAuthDataItem(0,
+							  g_pars.vec.rand,
+							  g_pars.vec.ik,
+							  g_pars.vec.ck,
+							  g_pars.vec.autn,
+							  g_pars.vec.auts);
+	/* Send MAA to translator; expect it to show up on GSUP side */
+	SWx.send(ts_DIA_SWx_MAA(g_pars.imsi, sip_auth_data_item,
+				sess_id := sess_id,
+				hbh_id := rx_mar.hop_by_hop_id,
+				ete_id := rx_mar.end_to_end_id));
+}
+
+private function f_DIA_SWx_tx_MAA_error(PDU_DIAMETER rx_mar, template (value) GenericAVP result) runs on EPDG_ConnHdlr {
+	var template (omit) AVP avp;
+	var octetstring sess_id;
+	var template (value) GenericAVP sip_auth_data_item;
+
+	avp := f_DIAMETER_get_avp(rx_mar, c_AVP_Code_BASE_NONE_Session_Id);
+	sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+	sip_auth_data_item := ts_AVP_3GPP_SIPAuthDataItem(0,
+							  g_pars.vec.rand,
+							  g_pars.vec.ik,
+							  g_pars.vec.ck,
+							  g_pars.vec.autn,
+							  g_pars.vec.auts);
+	SWx.send(ts_DIA_SWx_MAA_result(g_pars.imsi, result,
+				       sess_id := sess_id,
+				       hbh_id := rx_mar.hop_by_hop_id,
+				       ete_id := rx_mar.end_to_end_id));
+}
+
+/* Diameter SWx MAR + MAA. */
+private altstep as_DIA_SWx_MA_success() runs on EPDG_ConnHdlr {
+	var PDU_DIAMETER rx_dia;
 	[] SWx.receive(tr_DIA_SWx_MAR(g_pars.imsi)) -> value rx_dia {
-		avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
-		sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
-		sip_auth_data_item := ts_AVP_3GPP_SIPAuthDataItem(0,
-								  g_pars.vec.rand,
-								  g_pars.vec.ik,
-								  g_pars.vec.ck,
-								  g_pars.vec.autn,
-								  g_pars.vec.auts);
-		/* Send MAA to translator; expect it to show up on GSUP side */
-		SWx.send(ts_DIA_SWx_MAA(g_pars.imsi, sip_auth_data_item,
-					sess_id := sess_id,
-					hbh_id := rx_dia.hop_by_hop_id,
-					ete_id := rx_dia.end_to_end_id));
+		f_DIA_SWx_tx_MAA_success(rx_dia);
 		setverdict(pass);
 	}
 	[] SWx.receive(PDU_DIAMETER:?) -> value rx_dia {
@@ -729,28 +754,47 @@
 	}
 }
 
-/* GSUP AuthInfo Req + Resp, triggers SWx MAR + MAA. */
-private function f_GSUP_AI_success() runs on EPDG_ConnHdlr {
+private function f_GSUP_tx_SAI_REQ() runs on EPDG_ConnHdlr {
 	var GSUP_PDU rx_gsup;
-	var template (present) GSUP_IE auth_tuple_ie;
 	var template (value) GSUP_IEs pdp_info;
-	auth_tuple_ie := tr_GSUP_IE_AuthTuple3G(g_pars.vec.rand,
-						g_pars.vec.ik,
-						g_pars.vec.ck,
-						g_pars.vec.autn,
-						g_pars.vec.rand & g_pars.vec.auts);
 	pdp_info := { ts_GSUP_IE_PDP_CONTEXT_ID('00'O),
 		      ts_GSUP_IE_PDP_ADDRESS(ts_EuaIPv4Dyn),
 		      ts_GSUP_IE_APN(f_enc_dns_hostname(g_pars.apn)) };
 	GSUP.send(ts_GSUP_SAI_REQ_PDP_INFO(g_pars.imsi, pdp_info));
-	as_DIA_SWx_MA_success();
-	/* Expect a positive response back to the translator; expect AIA */
-	alt {
-	[] GSUP.receive(tr_GSUP_SAI_RES(g_pars.imsi, auth_tuple_ie));
+}
+
+
+private altstep as_GSUP_rx_SAI_RES() runs on EPDG_ConnHdlr {
+	var GSUP_PDU rx_gsup;
+	var template (present) GSUP_IE auth_tuple_ie := tr_GSUP_IE_AuthTuple3G(
+						g_pars.vec.rand,
+						g_pars.vec.ik,
+						g_pars.vec.ck,
+						g_pars.vec.autn,
+						g_pars.vec.rand & g_pars.vec.auts);
+
+	[] GSUP.receive(tr_GSUP_SAI_RES(g_pars.imsi, auth_tuple_ie)) -> value rx_gsup {
+	}
 	[] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
 		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
-		}
 	}
+}
+
+private altstep as_GSUP_rx_SAI_ERR(template (present) integer cause := ?) runs on EPDG_ConnHdlr {
+	var GSUP_PDU rx_gsup;
+
+	[] GSUP.receive(tr_GSUP_SAI_ERR(g_pars.imsi, cause)) -> value rx_gsup {
+	}
+	[] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+	}
+}
+
+/* GSUP AuthInfo Req + Resp, triggers SWx MAR + MAA. */
+private function f_GSUP_AI_success() runs on EPDG_ConnHdlr {
+	f_GSUP_tx_SAI_REQ();
+	as_DIA_SWx_MA_success();
+	as_GSUP_rx_SAI_RES();
 	setverdict(pass);
 }
 
@@ -863,6 +907,27 @@
 	setverdict(pass);
 }
 
+private function f_TC_authinfo_MAA_unknown_user(charstring id) runs on EPDG_ConnHdlr {
+	var PDU_DIAMETER rx_dia;
+	var DIAMETER_ExperimentalResultcode exp_result_code := DIAMETER_ERROR_USER_UNKNOWN;
+	f_GSUP_tx_SAI_REQ();
+
+	SWx.receive(tr_DIA_SWx_MAR(g_pars.imsi)) -> value rx_dia;
+	f_DIA_SWx_tx_MAA_error(rx_dia,
+			       ts_AVP_ExperimentalResult(vendor_id_3GPP,
+							 int2oct(enum2int(exp_result_code), 4)));
+	/* cause 2 = IMSI_UNKNOWN */
+	as_GSUP_rx_SAI_ERR(2);
+}
+testcase TC_authinfo_MAA_unknown_user() runs on MTC_CT {
+	var EPDG_ConnHdlrPars pars := f_init_pars();
+	var EPDG_ConnHdlr vc_conn;
+	f_init();
+	vc_conn := f_start_handler(refers(f_TC_authinfo_MAA_unknown_user), pars);
+	vc_conn.done;
+	setverdict(pass);
+}
+
 private function f_TC_ho_lte_to_wifi(charstring id) runs on EPDG_ConnHdlr {
 	f_initial_attach();
 	/* Whenever UE comes from 3GPP, PGW may activate a dedicated S2b bearer
@@ -998,6 +1063,7 @@
 
 control {
 	execute ( TC_authinfo_normal() );
+	execute ( TC_authinfo_MAA_unknown_user() );
 	execute ( TC_ho_lte_to_wifi() );
 	execute ( TC_ho_wifi_to_lte() );
 	execute ( TC_s2b_CreateSession_rejected() );
diff --git a/library/DIAMETER_Templates.ttcn b/library/DIAMETER_Templates.ttcn
index 5390d6e..338899f 100644
--- a/library/DIAMETER_Templates.ttcn
+++ b/library/DIAMETER_Templates.ttcn
@@ -337,11 +337,11 @@
 	}
 }
 
-template (value) GenericAVP ts_AVP_VendorId(Vendor_Id vendor_id) := {
+template (value) GenericAVP ts_AVP_VendorId(template (value) Vendor_Id vendor_id) := {
 	avp := {
 		avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Vendor_Id, '00000000'B),
 		avp_data := {
-			avp_BASE_NONE_Vendor_Id := int2oct(enum2int(vendor_id), 4)
+			avp_BASE_NONE_Vendor_Id := int2oct(enum2int(valueof(vendor_id)), 4)
 		}
 	}
 }
@@ -522,6 +522,14 @@
 		}
 	}
 }
+template (value) GenericAVP ts_AVP_ExperimentalResultCode(template (value) AVP_Unsigned32 n) := {
+	avp := {
+		avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Experimental_Result_Code),
+		avp_data := {
+			avp_BASE_NONE_Experimental_Result_Code := n
+		}
+	}
+}
 
 template (present) GenericAVP tr_AVP_ExperimentalResult(template (present) Vendor_Id vendor_id := ?,
 							template (present) AVP_Unsigned32 err_code := ?
@@ -536,6 +544,19 @@
 		}
 	}
 }
+template (value) GenericAVP ts_AVP_ExperimentalResult(template (value) Vendor_Id vendor_id := vendor_id_3GPP,
+						      template (value) AVP_Unsigned32 err_code
+							) := {
+	avp := {
+		avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Experimental_Result),
+		avp_data := {
+			avp_BASE_NONE_Experimental_Result := {
+				ts_AVP_VendorId(vendor_id),
+				ts_AVP_ExperimentalResultCode(err_code)
+			}
+		}
+	}
+}
 
 template (value) GenericAVP ts_AVP_SuppVendorIdRaw(uint32_t vendor_id) := {
 	avp := {
diff --git a/library/DIAMETER_ts29_273_Templates.ttcn b/library/DIAMETER_ts29_273_Templates.ttcn
index 899dfb4..f0ac442 100644
--- a/library/DIAMETER_ts29_273_Templates.ttcn
+++ b/library/DIAMETER_ts29_273_Templates.ttcn
@@ -180,6 +180,30 @@
 			ts_AVP_3GPP_SIPNumAuthDataItems(1)
 	});
 
+template (value) PDU_DIAMETER
+ts_DIA_SWx_MAA_result(template (value) hexstring imsi,
+		      template (value) GenericAVP result,
+		      template (value) uint32_t vendor_app_id := c_DIAMETER_3GPP_SWx_AID,
+		      template (value) octetstring sess_id := c_def_sess_id,
+		      template (value) charstring orig_host := "hss.localdomain",
+		      template (value) charstring orig_realm := "localdomain",
+		      template (value) UINT32 hbh_id := '00000000'O,
+		      template (value) UINT32 ete_id := '00000000'O) :=
+	ts_DIAMETER(flags := '01000000'B,
+		    cmd_code := Multimedia_Auth,
+		    app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+		    hbh_id := hbh_id,
+		    ete_id := ete_id,
+		    avps := {
+			ts_AVP_SessionId(sess_id),
+			ts_AVP_VendorSpecAppId(vendor_id_3GPP, valueof(vendor_app_id)),
+			result,
+			ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+			ts_AVP_OriginHost(orig_host),
+			ts_AVP_OriginRealm(orig_realm),
+			ts_AVP_UserNameImsi(valueof(imsi))
+	});
+
 /* Server-Assignment-Request,
  * 3GPP TS 29.273 8.1.2.2.2 UE/PDN Registration/DeRegistration Notification
  * 3GPP TS 29.273 8.2.2.3 Non-3GPP IP Access Registration Procedure */
diff --git a/library/GSUP_Templates.ttcn b/library/GSUP_Templates.ttcn
index 9daf9c0..6d14b02 100644
--- a/library/GSUP_Templates.ttcn
+++ b/library/GSUP_Templates.ttcn
@@ -374,7 +374,7 @@
 	ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT, {
 		valueof(ts_GSUP_IE_IMSI(imsi)), auth_tuple });
 
-template GSUP_PDU tr_GSUP_SAI_ERR(template hexstring imsi, template integer cause) :=
+template GSUP_PDU tr_GSUP_SAI_ERR(template hexstring imsi, template (present) integer cause := ?) :=
 	tr_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR, {
 			tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_Cause(cause) });