From 4d1388001aef49eb0c09908a9144815045269cfd Mon Sep 17 00:00:00 2001 From: Martin Kacer Date: Thu, 8 Nov 2018 10:32:15 +0100 Subject: [PATCH] Performance improvements for both DiameterFW and SS7FW. Performance tests modules updated. --- .../java/diameterfw/DiameterFirewall.java | 849 +++++----- .../DiameterFirewallPerformanceTests.java | 46 +- .../src/main/java/sigfw/common/Crypto.java | 282 +++- .../src/main/java/ss7fw/SS7Firewall.java | 1501 +++++++++-------- .../ss7fw/SS7FirewallPerformanceTests.java | 79 +- .../sigfw/tests/Test_DiameterFirewall.java | 5 + .../java/sigfw/tests/Test_SS7Firewall.java | 43 + 7 files changed, 1596 insertions(+), 1209 deletions(-) diff --git a/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewall.java b/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewall.java index d7068ac..934784f 100644 --- a/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewall.java +++ b/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewall.java @@ -109,6 +109,8 @@ import java.net.URLClassLoader; import java.security.interfaces.ECPublicKey; import com.p1sec.sigfw.SigFW_interface.FirewallRulesInterface; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.mobicents.protocols.sctp.netty.NettyAssociationImpl; import org.mobicents.protocols.sctp.netty.NettySctpManagementImpl; import sigfw.common.Crypto; @@ -141,6 +143,8 @@ private static void configLog4j() { private AvpDictionary dictionary = AvpDictionary.INSTANCE; private Stack stack; + // Executor Threads + ExecutorService threadPool = Executors.newFixedThreadPool(16); // //////////////////////////////////////// // Objects which will be used in action // @@ -163,7 +167,7 @@ private static void configLog4j() { private static Map sctpAssciationsMaxOutboundStreams = new HashMap(); // Diameter - public final MessageParser parser = new MessageParser(); + public static final MessageParser parser = new MessageParser(); static private String configName = "diameterfw.json"; @@ -949,467 +953,476 @@ private void firewallMessage(Association origin_asctn, int payloadProtocolId, in } - public void onPayload(Association asctn, PayloadData pd) { - //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - logger.debug("[[[[[[[[[[ onPayload ]]]]]]]]]]"); + public void onPayload(final Association asctn, final PayloadData pd) { - // LUA variables - HashMap lua_hmap = new HashMap(); - lua_hmap.put("diameter_orig_host", ""); - lua_hmap.put("diameter_orig_realm", ""); - lua_hmap.put("diameter_dest_host", ""); - lua_hmap.put("diameter_dest_realm", ""); - lua_hmap.put("diameter_cc", ""); // command code - lua_hmap.put("diameter_ai", ""); // application id - lua_hmap.put("diameter_imsi", ""); - lua_hmap.put("diameter_msisdn", ""); + threadPool.execute(new Runnable() { + @Override + public void run() { - ByteBuffer buf = ByteBuffer.wrap(pd.getData()); + //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + logger.debug("[[[[[[[[[[ onPayload ]]]]]]]]]]"); - - // Diameter firewall / filtering - try { - Message msg = this.parser.createMessage(buf); - - //logger.debug("Message = " + msg.getAvps().toString()); - - // Parse Values - long ai = msg.getApplicationId(); - lua_hmap.put("diameter_ai", Long.toString(ai)); - - int cc = msg.getCommandCode(); - lua_hmap.put("diameter_cc", Integer.toString(cc)); - - String dest_realm = ""; - Avp avp = msg.getAvps().getAvp(Avp.DESTINATION_REALM); - if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { - dest_realm = avp.getDiameterURI().getFQDN(); - } - lua_hmap.put("diameter_dest_realm", dest_realm); - - String dest_host = ""; - avp = msg.getAvps().getAvp(Avp.DESTINATION_HOST); - if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { - dest_host = avp.getDiameterURI().getFQDN(); - } - lua_hmap.put("diameter_dest_host", dest_host); - - String orig_realm = ""; - avp = msg.getAvps().getAvp(Avp.ORIGIN_REALM); - if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { - orig_realm = avp.getDiameterURI().getFQDN(); - } - lua_hmap.put("diameter_orig_realm", orig_realm); - - String orig_host = ""; - avp = msg.getAvps().getAvp(Avp.ORIGIN_HOST); - if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { - orig_host = avp.getDiameterURI().getFQDN(); - } - lua_hmap.put("diameter_orig_host", orig_host); - - String imsi = ""; - avp = msg.getAvps().getAvp(Avp.USER_NAME); - if (avp != null && avp.getUTF8String() != null) { - imsi = avp.getUTF8String() ; - } - lua_hmap.put("diameter_imsi", imsi); - - String msisdn = ""; - avp = msg.getAvps().getAvp(1400 /*Subscription-Data in ULA on S6a*/); - if (avp != null && avp.getGrouped() != null && avp.getGrouped().getAvp(Avp.MSISDN) != null) { - msisdn = avp.getGrouped().getAvp(Avp.MSISDN).getUTF8String() ; - } - lua_hmap.put("diameter_msisdn", msisdn); - - // ------ Request/Answer correlation -------- - // Store the Diameter session, to be able encrypt also answers. Store Origin Realm from Request - if (!dest_realm.equals("") && msg.isRequest()) { - String session_id = ai + ":" + cc + ":" + dest_realm + ":" + msg.getEndToEndIdentifier() + ":" + msg.getHopByHopIdentifier(); - diameter_sessions.put(session_id, orig_realm); - } - // ------------------------------------------ - - // ----------- Pass CER, DWR, DPR ----------- - if (cc == 257 || cc == 280 || cc == 282) { - sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, true, lua_hmap); - return; - } - // ------------------------------------------ - - // ---------- Diameter decryption ----------- - // Diameter Decryption - // Requests containing Dest-Realm - if (!dest_realm.equals("") && msg.isRequest()) { - if (DiameterFirewallConfig.destination_realm_decryption.containsKey(dest_realm)) { - KeyPair keyPair = DiameterFirewallConfig.destination_realm_decryption.get(dest_realm); - - // decrypt - String r = crypto.diameterDecrypt(msg, keyPair); - if (!r.equals("")) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, r, lua_hmap); - return; + // LUA variables + HashMap lua_hmap = new HashMap(); + lua_hmap.put("diameter_orig_host", ""); + lua_hmap.put("diameter_orig_realm", ""); + lua_hmap.put("diameter_dest_host", ""); + lua_hmap.put("diameter_dest_realm", ""); + lua_hmap.put("diameter_cc", ""); // command code + lua_hmap.put("diameter_ai", ""); // application id + lua_hmap.put("diameter_imsi", ""); + lua_hmap.put("diameter_msisdn", ""); + + ByteBuffer buf = ByteBuffer.wrap(pd.getData()); + + + // Diameter firewall / filtering + try { + Message msg = DiameterFirewall.parser.createMessage(buf); + + //logger.debug("Message = " + msg.getAvps().toString()); + + // Parse Values + long ai = msg.getApplicationId(); + lua_hmap.put("diameter_ai", Long.toString(ai)); + + int cc = msg.getCommandCode(); + lua_hmap.put("diameter_cc", Integer.toString(cc)); + + String dest_realm = ""; + Avp avp = msg.getAvps().getAvp(Avp.DESTINATION_REALM); + if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { + dest_realm = avp.getDiameterURI().getFQDN(); } - } - } - // Answers without Dest-Realm, but seen previously Request - else if (!msg.isRequest()) { - String _dest_realm = ""; - String session_id = ai + ":" + cc + ":" + orig_realm + ":" + msg.getEndToEndIdentifier() + ":" + msg.getHopByHopIdentifier(); - if (diameter_sessions.containsKey(session_id)) { - _dest_realm = diameter_sessions.get(session_id); - } - if (DiameterFirewallConfig.destination_realm_decryption.containsKey(_dest_realm)) { - KeyPair keyPair = DiameterFirewallConfig.destination_realm_decryption.get(_dest_realm); - logger.debug("Diameter Decryption of Answer for Destination Realm = " + _dest_realm); - - // decrypt - String r = crypto.diameterDecrypt(msg, keyPair); - if (!r.equals("")) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, r, lua_hmap); + lua_hmap.put("diameter_dest_realm", dest_realm); + + String dest_host = ""; + avp = msg.getAvps().getAvp(Avp.DESTINATION_HOST); + if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { + dest_host = avp.getDiameterURI().getFQDN(); + } + lua_hmap.put("diameter_dest_host", dest_host); + + String orig_realm = ""; + avp = msg.getAvps().getAvp(Avp.ORIGIN_REALM); + if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { + orig_realm = avp.getDiameterURI().getFQDN(); + } + lua_hmap.put("diameter_orig_realm", orig_realm); + + String orig_host = ""; + avp = msg.getAvps().getAvp(Avp.ORIGIN_HOST); + if (avp != null && avp.getDiameterURI() != null && avp.getDiameterURI().getFQDN() != null) { + orig_host = avp.getDiameterURI().getFQDN(); + } + lua_hmap.put("diameter_orig_host", orig_host); + + String imsi = ""; + avp = msg.getAvps().getAvp(Avp.USER_NAME); + if (avp != null && avp.getUTF8String() != null) { + imsi = avp.getUTF8String() ; + } + lua_hmap.put("diameter_imsi", imsi); + + String msisdn = ""; + avp = msg.getAvps().getAvp(1400 /*Subscription-Data in ULA on S6a*/); + if (avp != null && avp.getGrouped() != null && avp.getGrouped().getAvp(Avp.MSISDN) != null) { + msisdn = avp.getGrouped().getAvp(Avp.MSISDN).getUTF8String() ; + } + lua_hmap.put("diameter_msisdn", msisdn); + + // ------ Request/Answer correlation -------- + // Store the Diameter session, to be able encrypt also answers. Store Origin Realm from Request + if (!dest_realm.equals("") && msg.isRequest()) { + String session_id = ai + ":" + cc + ":" + dest_realm + ":" + msg.getEndToEndIdentifier() + ":" + msg.getHopByHopIdentifier(); + diameter_sessions.put(session_id, orig_realm); + } + // ------------------------------------------ + + // ----------- Pass CER, DWR, DPR ----------- + if (cc == 257 || cc == 280 || cc == 282) { + sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, true, lua_hmap); return; } - - diameter_sessions.remove(session_id); - } - } - // ------------------------------------------ - - - // Diameter firewall / filtering - - // TODO Origin Host whitelist - // TODO Origin Realm whitelist - - if(!DiameterFirewallConfig.check_diameter_application_id_whitelist(Long.toString(ai))) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked Application ID = " + ai, lua_hmap); - return; - } - - if(DiameterFirewallConfig.check_diameter_command_code_blacklist(Integer.toString(cc))) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked Command Code = " + cc, lua_hmap); - return; - } - - - avp = msg.getAvps().getAvp(Avp.ORIGIN_HOST); - if (avp != null) { - logger.debug("Origin Host = " + avp.getDiameterURI().getFQDN()); - } - avp = msg.getAvps().getAvp(Avp.ORIGIN_REALM); - if (avp != null) { - logger.debug("Origin Realm = " + avp.getDiameterURI().getFQDN()); - if(DiameterFirewallConfig.check_diameter_origin_realm_blacklist(avp.getDiameterURI().getFQDN())) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked Origin Realm = " + avp.getDiameterURI().getFQDN(), lua_hmap); - return; - } - } - - // Diameter Cat2 - if (msg.isRequest()) { - if (DiameterFirewallConfig.diameter_cat2_command_code_blacklist.containsKey(Integer.toString(cc))) { - // If towards HPLMN and not originated from HPLMN - if (DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) - && !DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm)) { - - // Drop if message targets IMSI in HPLMN - if (imsi != null) { - // IMSI prefix check - for (String imsi_prefix: DiameterFirewallConfig.hplmn_imsi.keySet()) { - if (imsi.startsWith(imsi_prefix)) { - // logger.info("============ Diameter Cat2 Blocked Command Code = " + cc" ============"); - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW (Cat2): Blocked targeting home IMSI", lua_hmap); - return; - } + // ------------------------------------------ + + // ---------- Diameter decryption ----------- + // Diameter Decryption + // Requests containing Dest-Realm + if (!dest_realm.equals("") && msg.isRequest()) { + if (DiameterFirewallConfig.destination_realm_decryption.containsKey(dest_realm)) { + KeyPair keyPair = DiameterFirewallConfig.destination_realm_decryption.get(dest_realm); + + // decrypt + String r = crypto.diameterDecrypt(msg, keyPair); + if (!r.equals("")) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, r, lua_hmap); + return; } } } + // Answers without Dest-Realm, but seen previously Request + else if (!msg.isRequest()) { + String _dest_realm = ""; + String session_id = ai + ":" + cc + ":" + orig_realm + ":" + msg.getEndToEndIdentifier() + ":" + msg.getHopByHopIdentifier(); + if (diameter_sessions.containsKey(session_id)) { + _dest_realm = diameter_sessions.get(session_id); + } + if (DiameterFirewallConfig.destination_realm_decryption.containsKey(_dest_realm)) { + KeyPair keyPair = DiameterFirewallConfig.destination_realm_decryption.get(_dest_realm); + logger.debug("Diameter Decryption of Answer for Destination Realm = " + _dest_realm); + + // decrypt + String r = crypto.diameterDecrypt(msg, keyPair); + if (!r.equals("")) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, r, lua_hmap); + return; + } - } - } - // -------------- Externel Firewall rules ----------------- - if (externalFirewallRules.diameterFirewallRules(asctn, pd) == false) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Match with Externel Firewall rules", lua_hmap); - return; - } - - // -------------- LUA rules ----------------- - ScriptEngineManager mgr = new ScriptEngineManager(); - ScriptEngine eng = mgr.getEngineByName("luaj"); - for (String key : lua_hmap.keySet()) { - eng.put(key, lua_hmap.get(key)); - } + diameter_sessions.remove(session_id); + } + } + // ------------------------------------------ - boolean lua_match = false; - int i; - for (i = 0; i < DiameterFirewallConfig.lua_blacklist_rules.size(); i++) { - try { - eng.eval("y = " + (String)DiameterFirewallConfig.lua_blacklist_rules.get(i)); - boolean r = Boolean.valueOf(eng.get("y").toString()); - lua_match |= r; - if (r) { - //logger.debug("============ LUA rules blacklist: " + DiameterFirewallConfig.lua_blacklist_rules.get(i) + " ============"); - //logger.debug("============ LUA variables ============"); - //for (String key : lua_hmap.keySet()) { - // logger.debug(key + ": " + lua_hmap.get(key)); - //} - break; + + // Diameter firewall / filtering + + // TODO Origin Host whitelist + // TODO Origin Realm whitelist + + if(!DiameterFirewallConfig.check_diameter_application_id_whitelist(Long.toString(ai))) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked Application ID = " + ai, lua_hmap); + return; } - } catch (ScriptException ex) { - java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); - } - } - if (lua_match) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Match with Lua rule " + i, lua_hmap); - return; - } - // ------------------------------------------ - - // ------------- IDS API rules --------------- - if (connectorIDS != null) { - try { - if(connectorIDS.evalDiameterMessage(DatatypeConverter.printHexBinary(pd.getData())) == false) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked by IDS " + i, lua_hmap); + + if(DiameterFirewallConfig.check_diameter_command_code_blacklist(Integer.toString(cc))) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked Command Code = " + cc, lua_hmap); return; } - } catch (Exception ex) { - // TODO - } - } - // ------------------------------------------ - - // Encryption Autodiscovery Sending Result - // Only targeting HPLMN - if (cc == CC_AUTO_ENCRYPTION - && DiameterFirewallConfig.encryption_autodiscovery.equals("true") - && msg.isRequest() - && DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) - && !DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm) - ) { - - if (DiameterFirewallConfig.destination_realm_decryption.containsKey(dest_realm)) { - KeyPair myKeyPair = DiameterFirewallConfig.destination_realm_decryption.get(dest_realm); - if (myKeyPair != null) { - Answer answer = ((IMessage)(msg)).createAnswer(ResultCode.SUCCESS); - - // Capabilities - // TODO - answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_CAPABILITIES, "Av1".getBytes()); - - // Realm - answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_REALM, dest_realm.getBytes()); - - // Public key type - String publicKeyType = ""; - if (myKeyPair.getPublic() instanceof RSAPublicKey) { - publicKeyType = "RSA"; - } else if (myKeyPair.getPublic() instanceof ECPublicKey) { - publicKeyType = "EC"; + + + avp = msg.getAvps().getAvp(Avp.ORIGIN_HOST); + if (avp != null) { + logger.debug("Origin Host = " + avp.getDiameterURI().getFQDN()); + } + avp = msg.getAvps().getAvp(Avp.ORIGIN_REALM); + if (avp != null) { + logger.debug("Origin Realm = " + avp.getDiameterURI().getFQDN()); + if(DiameterFirewallConfig.check_diameter_origin_realm_blacklist(avp.getDiameterURI().getFQDN())) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked Origin Realm = " + avp.getDiameterURI().getFQDN(), lua_hmap); + return; } - answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY_TYPE, publicKeyType.getBytes()); - - // Public key - answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY,myKeyPair.getPublic().getEncoded()); - - logger.info("============ Encryption Autodiscovery Sending Result ============ "); - - sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), answer, false, lua_hmap); - return; } - } - } - - // Encryption Autodiscovery Receiving Result - // Only targeting HPLMN - if (cc == CC_AUTO_ENCRYPTION - && DiameterFirewallConfig.encryption_autodiscovery.equals("true") - && !msg.isRequest() - // Answer does not contain currently realms - //&& DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) - //&& !DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm) - ) { - - logger.info("============ Encryption Autodiscovery Receiving Result ============ "); - logger.debug("encryption_autodiscovery_sessions.containsKey " + new Long(msg.getEndToEndIdentifier()).toString()); - if (encryption_autodiscovery_sessions.containsKey(msg.getEndToEndIdentifier()) - // Answer does not contain currently realms - //&& encryption_autodiscovery_sessions.get(msg.getEndToEndIdentifier()).equals(origin_realm) - && msg.getAvps() != null) { - logger.debug("Processing Autodiscovery Result"); - - // Capabilities - // TODO - - // Realm prefix - String realm = ""; - if (msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_REALM) != null) { - byte[] d2 = msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_REALM).getOctetString(); - realm = new String(d2); + + // Diameter Cat2 + if (msg.isRequest()) { + if (DiameterFirewallConfig.diameter_cat2_command_code_blacklist.containsKey(Integer.toString(cc))) { + // If towards HPLMN and not originated from HPLMN + if (DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) + && !DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm)) { + + // Drop if message targets IMSI in HPLMN + if (imsi != null) { + // IMSI prefix check + for (String imsi_prefix: DiameterFirewallConfig.hplmn_imsi.keySet()) { + if (imsi.startsWith(imsi_prefix)) { + // logger.info("============ Diameter Cat2 Blocked Command Code = " + cc" ============"); + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW (Cat2): Blocked targeting home IMSI", lua_hmap); + return; + } + } + } + } + + } } - - // Public key type - String publicKeyType = "RSA"; - if (msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY_TYPE) != null) { - byte[] d3 = msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY_TYPE).getOctetString(); - - publicKeyType = new String(d3); + // -------------- Externel Firewall rules ----------------- + if (externalFirewallRules.diameterFirewallRules(asctn, pd) == false) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Match with Externel Firewall rules", lua_hmap); + return; } - - // Public key - if (msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY) != null) { - byte[] d4 = msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY).getOctetString(); - // TODO add method into config to add public key - byte[] publicKeyBytes = d4; + + // -------------- LUA rules ----------------- + ScriptEngineManager mgr = new ScriptEngineManager(); + ScriptEngine eng = mgr.getEngineByName("luaj"); + for (String key : lua_hmap.keySet()) { + eng.put(key, lua_hmap.get(key)); + } + + boolean lua_match = false; + int i; + for (i = 0; i < DiameterFirewallConfig.lua_blacklist_rules.size(); i++) { try { - X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes); - PublicKey publicKey = null; - - if (publicKeyType.equals("RSA")) { - publicKey = keyFactoryRSA.generatePublic(pubKeySpec); - } else if (publicKeyType.equals("EC")) { - publicKey = keyFactoryEC.generatePublic(pubKeySpec); + eng.eval("y = " + (String)DiameterFirewallConfig.lua_blacklist_rules.get(i)); + boolean r = Boolean.valueOf(eng.get("y").toString()); + lua_match |= r; + if (r) { + //logger.debug("============ LUA rules blacklist: " + DiameterFirewallConfig.lua_blacklist_rules.get(i) + " ============"); + //logger.debug("============ LUA variables ============"); + //for (String key : lua_hmap.keySet()) { + // logger.debug(key + ": " + lua_hmap.get(key)); + //} + break; } - logger.debug("Adding public key for realm = " + realm); - DiameterFirewallConfig.destination_realm_encryption.put(realm, publicKey); - } catch (InvalidKeySpecException ex) { + } catch (ScriptException ex) { java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); } } - } - - // do not forward message - return; - } - - // --------------- Diameter signature --------------- - // Sign only Requests containing Orig-Realm - if (!orig_realm.equals("") && msg.isRequest()) { - // ------------- Diameter verify -------------- - if (DiameterFirewallConfig.origin_realm_verify.containsKey(orig_realm)) { - PublicKey publicKey = DiameterFirewallConfig.origin_realm_verify.get(orig_realm); - String r = crypto.diameterVerify(msg, publicKey); - if (!r.equals("")) { - firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, r, lua_hmap); + if (lua_match) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Match with Lua rule " + i, lua_hmap); return; } - } - // No key to verify signature - else { - // TODO could initiate key autodiscovery - } - // -------------------------------------------- - // ------------- Diameter signing ------------- - if (DiameterFirewallConfig.origin_realm_signing.containsKey(orig_realm)) { - KeyPair keyPair = DiameterFirewallConfig.origin_realm_signing.get(orig_realm); - crypto.diameterSign(msg, keyPair); - } - // -------------------------------------------- - } - // ------------------------------------------ - - - // ---------- Diameter encryption ----------- - String session_id = ai + ":" + cc + ":" + orig_realm + ":" + msg.getEndToEndIdentifier() + ":" + msg.getHopByHopIdentifier(); - - // Requests containing Dest-Realm - if (!dest_realm.equals("") && msg.isRequest() && DiameterFirewallConfig.destination_realm_encryption.containsKey(dest_realm)) { - PublicKey publicKey = DiameterFirewallConfig.destination_realm_encryption.get(dest_realm); - logger.debug("Diameter Encryption of Request for Destination Realm = " + dest_realm); - - // encrypt - // diameterEncrypt(msg, publicKey); - // changed to v2 to use encrypted grouped AVP - crypto.diameterEncrypt_v2(msg, publicKey); - } - // Answers without Dest-Realm, but seen previous Request - else if (!msg.isRequest() - && diameter_sessions.containsKey(session_id) - && DiameterFirewallConfig.destination_realm_encryption.containsKey(diameter_sessions.get(session_id)) - ) { - String _dest_realm = diameter_sessions.get(session_id); + // ------------------------------------------ - PublicKey publicKey = DiameterFirewallConfig.destination_realm_encryption.get(_dest_realm); - logger.debug("Diameter Encryption of Answer for Destination Realm = " + _dest_realm); + // ------------- IDS API rules --------------- + if (connectorIDS != null) { + try { + if(connectorIDS.evalDiameterMessage(DatatypeConverter.printHexBinary(pd.getData())) == false) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, "DIAMETER FW: Blocked by IDS " + i, lua_hmap); + return; + } + } catch (Exception ex) { + // TODO + } + } + // ------------------------------------------ + + // Encryption Autodiscovery Sending Result + // Only targeting HPLMN + if (cc == CC_AUTO_ENCRYPTION + && DiameterFirewallConfig.encryption_autodiscovery.equals("true") + && msg.isRequest() + && DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) + && !DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm) + ) { + + if (DiameterFirewallConfig.destination_realm_decryption.containsKey(dest_realm)) { + KeyPair myKeyPair = DiameterFirewallConfig.destination_realm_decryption.get(dest_realm); + if (myKeyPair != null) { + Answer answer = ((IMessage)(msg)).createAnswer(ResultCode.SUCCESS); + + // Capabilities + // TODO + answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_CAPABILITIES, "Av1".getBytes()); + + // Realm + answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_REALM, dest_realm.getBytes()); + + // Public key type + String publicKeyType = ""; + if (myKeyPair.getPublic() instanceof RSAPublicKey) { + publicKeyType = "RSA"; + } else if (myKeyPair.getPublic() instanceof ECPublicKey) { + publicKeyType = "EC"; + } + answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY_TYPE, publicKeyType.getBytes()); - // encrypt - // diameterEncrypt(msg, publicKey); - // changed to v2 to use encrypted grouped AVP - crypto.diameterEncrypt_v2(msg, publicKey); + // Public key + answer.getAvps().addAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY,myKeyPair.getPublic().getEncoded()); - diameter_sessions.remove(session_id); + logger.info("============ Encryption Autodiscovery Sending Result ============ "); - } - // ------------ Encryption Autodiscovery ------------ - else if (DiameterFirewallConfig.encryption_autodiscovery.equals("true") - && - // If not encrypted Requests towards non HPLMN - ((msg.isRequest() - && !DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) - && DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm)) || - // In not encrypted Answers towards non HPLMN - (!msg.isRequest() - && diameter_sessions.containsKey(session_id)) - && !DiameterFirewallConfig.hplmn_realms.containsKey(diameter_sessions.get(session_id))) - ) { - String _dest_realm = dest_realm; - if(!msg.isRequest()) { - _dest_realm = diameter_sessions.get(session_id); - } + sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), answer, false, lua_hmap); + return; + } + } + } - if (!encryption_autodiscovery_sessions_reverse.containsKey(_dest_realm)) { + // Encryption Autodiscovery Receiving Result + // Only targeting HPLMN + if (cc == CC_AUTO_ENCRYPTION + && DiameterFirewallConfig.encryption_autodiscovery.equals("true") + && !msg.isRequest() + // Answer does not contain currently realms + //&& DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) + //&& !DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm) + ) { + + logger.info("============ Encryption Autodiscovery Receiving Result ============ "); + logger.debug("encryption_autodiscovery_sessions.containsKey " + new Long(msg.getEndToEndIdentifier()).toString()); + if (encryption_autodiscovery_sessions.containsKey(msg.getEndToEndIdentifier()) + // Answer does not contain currently realms + //&& encryption_autodiscovery_sessions.get(msg.getEndToEndIdentifier()).equals(origin_realm) + && msg.getAvps() != null) { + logger.debug("Processing Autodiscovery Result"); + + // Capabilities + // TODO + + // Realm prefix + String realm = ""; + if (msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_REALM) != null) { + byte[] d2 = msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_REALM).getOctetString(); + realm = new String(d2); + } - IMessage message = parser.createEmptyMessage((IMessage)msg, CC_AUTO_ENCRYPTION); + // Public key type + String publicKeyType = "RSA"; + if (msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY_TYPE) != null) { + byte[] d3 = msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY_TYPE).getOctetString(); - if(!msg.isRequest()) { - message.setRequest(true); - // TODO usa raw AVP encoding, because aaa:// is added by jDiameter - message.getAvps().addAvp(Avp.DESTINATION_REALM, _dest_realm, true, false, true); + publicKeyType = new String(d3); + } + + // Public key + if (msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY) != null) { + byte[] d4 = msg.getAvps().getAvp(AVP_AUTO_ENCRYPTION_PUBLIC_KEY).getOctetString(); + // TODO add method into config to add public key + byte[] publicKeyBytes = d4; + try { + X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes); + PublicKey publicKey = null; + + if (publicKeyType.equals("RSA")) { + publicKey = keyFactoryRSA.generatePublic(pubKeySpec); + } else if (publicKeyType.equals("EC")) { + publicKey = keyFactoryEC.generatePublic(pubKeySpec); + } + logger.debug("Adding public key for realm = " + realm); + DiameterFirewallConfig.destination_realm_encryption.put(realm, publicKey); + } catch (InvalidKeySpecException ex) { + java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + // do not forward message + return; } - message.setHeaderApplicationId(16777251); + // --------------- Diameter signature --------------- + // Sign only Requests containing Orig-Realm + if (!orig_realm.equals("") && msg.isRequest()) { + // ------------- Diameter verify -------------- + if (DiameterFirewallConfig.origin_realm_verify.containsKey(orig_realm)) { + PublicKey publicKey = DiameterFirewallConfig.origin_realm_verify.get(orig_realm); + String r = crypto.diameterVerify(msg, publicKey); + if (!r.equals("")) { + firewallMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, r, lua_hmap); + return; + } + } + // No key to verify signature + else { + // TODO could initiate key autodiscovery + } + // -------------------------------------------- + // ------------- Diameter signing ------------- + if (DiameterFirewallConfig.origin_realm_signing.containsKey(orig_realm)) { + KeyPair keyPair = DiameterFirewallConfig.origin_realm_signing.get(orig_realm); + crypto.diameterSign(msg, keyPair); + } + // -------------------------------------------- + } + // ------------------------------------------ - avp = msg.getAvps().getAvp(Avp.ORIGIN_REALM); - if (avp != null) { - message.getAvps().addAvp(avp); + + // ---------- Diameter encryption ----------- + String session_id = ai + ":" + cc + ":" + orig_realm + ":" + msg.getEndToEndIdentifier() + ":" + msg.getHopByHopIdentifier(); + + // Requests containing Dest-Realm + if (!dest_realm.equals("") && msg.isRequest() && DiameterFirewallConfig.destination_realm_encryption.containsKey(dest_realm)) { + PublicKey publicKey = DiameterFirewallConfig.destination_realm_encryption.get(dest_realm); + logger.debug("Diameter Encryption of Request for Destination Realm = " + dest_realm); + + // encrypt + // diameterEncrypt(msg, publicKey); + // changed to v2 to use encrypted grouped AVP + crypto.diameterEncrypt_v2(msg, publicKey); } + // Answers without Dest-Realm, but seen previous Request + else if (!msg.isRequest() + && diameter_sessions.containsKey(session_id) + && DiameterFirewallConfig.destination_realm_encryption.containsKey(diameter_sessions.get(session_id)) + ) { + String _dest_realm = diameter_sessions.get(session_id); + + PublicKey publicKey = DiameterFirewallConfig.destination_realm_encryption.get(_dest_realm); + logger.debug("Diameter Encryption of Answer for Destination Realm = " + _dest_realm); + + // encrypt + // diameterEncrypt(msg, publicKey); + // changed to v2 to use encrypted grouped AVP + crypto.diameterEncrypt_v2(msg, publicKey); + + diameter_sessions.remove(session_id); - // --------- Add also Diameter signature ------------ - if (DiameterFirewallConfig.origin_realm_signing.containsKey(orig_realm)) { - KeyPair keyPair = DiameterFirewallConfig.origin_realm_signing.get(orig_realm); - crypto.diameterSign(message, keyPair); } - // -------------------------------------------------- + // ------------ Encryption Autodiscovery ------------ + else if (DiameterFirewallConfig.encryption_autodiscovery.equals("true") + && + // If not encrypted Requests towards non HPLMN + ((msg.isRequest() + && !DiameterFirewallConfig.hplmn_realms.containsKey(dest_realm) + && DiameterFirewallConfig.hplmn_realms.containsKey(orig_realm)) || + // In not encrypted Answers towards non HPLMN + (!msg.isRequest() + && diameter_sessions.containsKey(session_id)) + && !DiameterFirewallConfig.hplmn_realms.containsKey(diameter_sessions.get(session_id))) + ) { + String _dest_realm = dest_realm; + if(!msg.isRequest()) { + _dest_realm = diameter_sessions.get(session_id); + } - logger.info("============ Sending Autodiscovery Request ============ "); + if (!encryption_autodiscovery_sessions_reverse.containsKey(_dest_realm)) { - // Workaround. E2E ID long value should be clamp to 32bit before use. It is clamped in proto encoding. - // See jDiamter MessageParser.java, Line 111. long endToEndId = ((long) in.readInt() << 32) >>> 32; - long e2e_id = ((long) message.getEndToEndIdentifier() << 32) >>> 32; - message.setEndToEndIdentifier(e2e_id); - // + IMessage message = parser.createEmptyMessage((IMessage)msg, CC_AUTO_ENCRYPTION); - sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), message, true, lua_hmap); + // Workaround. E2E ID long value should be clamp to 32bit before use. It is clamped in proto encoding. + // See jDiamter MessageParser.java, Line 111. long endToEndId = ((long) in.readInt() << 32) >>> 32; + long e2e_id = ((long) message.getEndToEndIdentifier() << 32) >>> 32; + message.setEndToEndIdentifier(e2e_id); + // + // to this as soon as possible to prevent concurrent threads to duplicate the autodiscovery + logger.debug("encryption_autodiscovery_sessions.put " + message.getEndToEndIdentifier() + " " + _dest_realm); + encryption_autodiscovery_sessions.put(message.getEndToEndIdentifier(), _dest_realm); + logger.debug("encryption_autodiscovery_sessions_reverse.put " + _dest_realm + " " + message.getEndToEndIdentifier()); + encryption_autodiscovery_sessions_reverse.put(_dest_realm, message.getEndToEndIdentifier()); - logger.debug("encryption_autodiscovery_sessions.put " + message.getEndToEndIdentifier() + " " + _dest_realm); - encryption_autodiscovery_sessions.put(message.getEndToEndIdentifier(), _dest_realm); - logger.debug("encryption_autodiscovery_sessions_reverse.put " + _dest_realm + " " + message.getEndToEndIdentifier()); - encryption_autodiscovery_sessions_reverse.put(_dest_realm, message.getEndToEndIdentifier()); - } + if(!msg.isRequest()) { + message.setRequest(true); + // TODO usa raw AVP encoding, because aaa:// is added by jDiameter + message.getAvps().addAvp(Avp.DESTINATION_REALM, _dest_realm, true, false, true); + } + + message.setHeaderApplicationId(16777251); + + avp = msg.getAvps().getAvp(Avp.ORIGIN_REALM); + if (avp != null) { + message.getAvps().addAvp(avp); + } + + // --------- Add also Diameter signature ------------ + if (DiameterFirewallConfig.origin_realm_signing.containsKey(orig_realm)) { + KeyPair keyPair = DiameterFirewallConfig.origin_realm_signing.get(orig_realm); + crypto.diameterSign(message, keyPair); + } + // -------------------------------------------------- + + logger.info("============ Sending Autodiscovery Request ============ "); + + sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), message, true, lua_hmap); + } + } + // ------------------------------------------------- + + sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, true, lua_hmap); + + } catch (AvpDataException ex) { + java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); + } catch (InvalidKeyException ex) { + java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); + }/* catch (URISyntaxException ex) { + java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); + } catch (UnknownServiceException ex) { + java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); + }*/ + } - // ------------------------------------------------- - - sendDiameterMessage(asctn, pd.getPayloadProtocolId(), pd.getStreamNumber(), msg, true, lua_hmap); - - } catch (AvpDataException ex) { - java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); - } catch (InvalidKeyException ex) { - java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); - }/* catch (URISyntaxException ex) { - java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); - } catch (UnknownServiceException ex) { - java.util.logging.Logger.getLogger(DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); - }*/ + }); + } public void onServiceStarted() { diff --git a/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewallPerformanceTests.java b/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewallPerformanceTests.java index 6f759e5..40629c3 100644 --- a/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewallPerformanceTests.java +++ b/sigfw/sigfw.sigfw/src/main/java/diameterfw/DiameterFirewallPerformanceTests.java @@ -30,10 +30,12 @@ import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.logging.Level; +import javax.xml.bind.DatatypeConverter; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.mobicents.protocols.api.Association; @@ -60,6 +62,7 @@ public class DiameterFirewallPerformanceTests implements ManagementEventListener private boolean sctpServerAssociationUp = false; NettyAssociationImpl clientAssociation = null; int messagesRecieved = 0; + int errorMessagesRecieved = 0; // IN, OUT MAX SCTP STREAMS private static Map sctpAssciationsMaxInboundStreams = new HashMap(); @@ -219,7 +222,7 @@ private void start() { long startTime = System.nanoTime(); - int max_messages = 20000; + int max_messages = 500000; for (int i = 0; i < max_messages; i++) { @@ -236,12 +239,13 @@ private void start() { if (i%100 == 0) { log.info("Messages sent ........ #" + i); log.info("Messages recieved ........ #" + messagesRecieved); + log.info("Error Messages recieved .. #" + errorMessagesRecieved); } - // if there is more than 2000 messages sent and not recieved + // if there is more than 5000 messages sent and not recieved // throttle sending to not overflow the recieving buffer - if (i - messagesRecieved > 2000) { - Thread.currentThread().sleep(100); + if (i - messagesRecieved > 5000) { + Thread.currentThread().sleep(10); } } @@ -253,6 +257,7 @@ private void start() { log.info("Messages sent ........ #" + max_messages); log.info("Messages recieved ........ #" + messagesRecieved); + log.info("Error Messages recieved .. #" + errorMessagesRecieved); } long estimatedTime = System.nanoTime() - startTime; @@ -419,6 +424,39 @@ public void onCommunicationRestart(Association asctn) { public void onPayload(Association asctn, PayloadData pd) { log.debug("[[[[[[[[[[ onPayload ]]]]]]]]]]"); + /*Thread thread = new Thread(){ + public void run(){ + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException ex) { + java.util.logging.Logger.getLogger(DiameterFirewallPerformanceTests.class.getName()).log(Level.SEVERE, null, ex); + } + log.info("ThreadId = " + Thread.currentThread().getId()); + } + }; + thread.start(); + + log.info("ThreadId = " + Thread.currentThread().getId());*/ + + ByteBuffer buf = ByteBuffer.wrap(pd.getData()); + byte[] arr = new byte[buf.remaining()]; + buf.get(arr); + + // OK - The same ULR as was sent was recieved + // 010000f88000013c0100002362e31f1209d000020000010740000037426164437573746f6d53657373696f6e49643b596573576543616e5061737349643b3135343134303438333235313400000001024000000c010000230000011b4000001c65786368616e67652e6578616d706c652e6f726700000108400000113132372e302e302e31000000000001284000002265786368616e6765436c69656e742e6578616d706c652e6f7267000000000001400000183131313131313131313131313131313100000760c00000100001046a00000000000007cfc00000230001046a492077616e7420746f20676574203320616e737765727300 + if (DatatypeConverter.printHexBinary(arr).equals("010000F88000013C0100002362E31F1209D000020000010740000037426164437573746F6D53657373696F6E49643B596573576543616E5061737349643B3135343134303438333235313400000001024000000C010000230000011B4000001C65786368616E67652E6578616D706C652E6F726700000108400000113132372E302E302E31000000000001284000002265786368616E6765436C69656E742E6578616D706C652E6F7267000000000001400000183131313131313131313131313131313100000760C00000100001046A00000000000007CFC00000230001046A492077616E7420746F20676574203320616E737765727300")) { + + } + // OK - ULR just differently ordered AVPs after 2 FWs + // 010000F88000013C0100002362E31F1209D000020000010740000037426164437573746F6D53657373696F6E49643B596573576543616E5061737349643B31353431343034383332353134000000011B4000001C65786368616E67652E6578616D706C652E6F726700000108400000113132372E302E302E31000000000001284000002265786368616E6765436C69656E742E6578616D706C652E6F72670000000007CFC00000230001046A492077616E7420746F20676574203320616E73776572730000000760C00000100001046A00000000000000014000001831313131313131313131313131313131000001024000000C01000023 + else if (DatatypeConverter.printHexBinary(arr).equals("010000F88000013C0100002362E31F1209D000020000010740000037426164437573746F6D53657373696F6E49643B596573576543616E5061737349643B31353431343034383332353134000000011B4000001C65786368616E67652E6578616D706C652E6F726700000108400000113132372E302E302E31000000000001284000002265786368616E6765436C69656E742E6578616D706C652E6F72670000000007CFC00000230001046A492077616E7420746F20676574203320616E73776572730000000760C00000100001046A00000000000000014000001831313131313131313131313131313131000001024000000C01000023")) { + + } + // report error + else { + log.warn(DatatypeConverter.printHexBinary(arr)); + errorMessagesRecieved++; + } messagesRecieved++; } diff --git a/sigfw/sigfw.sigfw/src/main/java/sigfw/common/Crypto.java b/sigfw/sigfw.sigfw/src/main/java/sigfw/common/Crypto.java index e363d3a..1d5dcfd 100644 --- a/sigfw/sigfw.sigfw/src/main/java/sigfw/common/Crypto.java +++ b/sigfw/sigfw.sigfw/src/main/java/sigfw/common/Crypto.java @@ -85,6 +85,7 @@ */ public class Crypto implements CryptoInterface { + /* // Encryption RSA public static KeyFactory keyFactoryRSA; public static Cipher cipherRSA; @@ -93,6 +94,7 @@ public class Crypto implements CryptoInterface { public static KeyFactory keyFactoryEC; public static Cipher cipherAES_GCM; public static Signature signatureECDSA; + */ static final private int AVP_ENCRYPTED = 1100; static final private int AVP_ENCRYPTED_GROUPED = 1101; @@ -112,6 +114,7 @@ public class Crypto implements CryptoInterface { } public Crypto() { + /* // Encryption RSA try { keyFactoryRSA = KeyFactory.getInstance("RSA"); @@ -135,6 +138,7 @@ public Crypto() { } catch (NoSuchProviderException ex) { java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } + */ } protected static void configLog4j() { @@ -154,6 +158,24 @@ protected static void configLog4j() { public void diameterSign(Message message, KeyPair keyPair) { //logger.debug("Message Sign = " + message.getAvps().toString()); + Signature signatureRSA = null; + Signature signatureECDSA = null; + + // Encryption RSA + try { + signatureRSA = Signature.getInstance("SHA256WithRSA"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + signatureECDSA = Signature.getInstance("SHA256withECDSA"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + if (keyPair != null) { PrivateKey privateKey = keyPair.getPrivate(); if(privateKey != null) { @@ -216,10 +238,10 @@ public void diameterSign(Message message, KeyPair keyPair) { byte[] signatureBytes = null; // RSA if (privateKey instanceof RSAPrivateKey) { - this.signatureRSA.initSign(privateKey); + signatureRSA.initSign(privateKey); - this.signatureRSA.update(dataToSign.getBytes()); - signatureBytes = this.signatureRSA.sign(); + signatureRSA.update(dataToSign.getBytes()); + signatureBytes = signatureRSA.sign(); } // EC else if (privateKey instanceof ECPrivateKey) { @@ -253,6 +275,16 @@ public String diameterVerify(Message message, PublicKey publicKey) { return ""; } + Signature signatureRSA = null; + Signature signatureECDSA = null; + + // Encryption RSA + try { + signatureRSA = Signature.getInstance("SHA256WithRSA"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + List signed_index = new ArrayList(); AvpSet avps = message.getAvps(); @@ -340,9 +372,9 @@ public String diameterVerify(Message message, PublicKey publicKey) { }*/ if (publicKey instanceof RSAPublicKey) { - this.signatureRSA.initVerify(publicKey); - this.signatureRSA.update(dataToSign.getBytes()); - if (signatureBytes != null && this.signatureRSA.verify(signatureBytes)) { + signatureRSA.initVerify(publicKey); + signatureRSA.update(dataToSign.getBytes()); + if (signatureBytes != null && signatureRSA.verify(signatureBytes)) { return ""; } } else if (publicKey instanceof ECPublicKey) { @@ -368,6 +400,31 @@ public String diameterVerify(Message message, PublicKey publicKey) { @Override public void diameterEncrypt(Message message, PublicKey publicKey) throws InvalidKeyException { + // Encryption RSA + Cipher cipherRSA = null; + // Encryption EC + Cipher cipherAES_GCM = null; + + // Encryption RSA + try { + cipherRSA = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + cipherAES_GCM = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchProviderException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + //logger.debug("== diameterEncrypt =="); AvpSet avps = message.getAvps(); @@ -404,18 +461,18 @@ public void diameterEncrypt(Message message, PublicKey publicKey) throws Invalid TVP[2] = (byte) ((t >> 8) & 0xFF); TVP[3] = (byte) ((t >> 0) & 0xFF); - //this.cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); - //byte[] cipherText = this.cipherRSA.doFinal(b); + //Crypto.cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); + //byte[] cipherText = Crypto.cipherRSA.doFinal(b); RSAPublicKey rsaPublicKey = (RSAPublicKey)publicKey; - this.cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); + cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); int keyLength = rsaPublicKey.getModulus().bitLength() / 8; byte[][] datas = splitByteArray(d, keyLength - 11 - 4); byte[] cipherText = null; for (byte[] b : datas) { - cipherText = concatByteArray(cipherText, this.cipherRSA.doFinal(concatByteArray(TVP, b))); + cipherText = concatByteArray(cipherText, cipherRSA.doFinal(concatByteArray(TVP, b))); } cipherText = concatByteArray(SPI, cipherText); @@ -443,6 +500,32 @@ public void diameterEncrypt(Message message, PublicKey publicKey) throws Invalid @Override public String diameterDecrypt(Message message, KeyPair keyPair) { + + // Encryption RSA + Cipher cipherRSA = null; + // Encryption EC + Cipher cipherAES_GCM = null; + + // Encryption RSA + try { + cipherRSA = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + cipherAES_GCM = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchProviderException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + //logger.debug("== diameterDecrypt =="); AvpSet avps = message.getAvps(); @@ -476,7 +559,7 @@ public String diameterDecrypt(Message message, KeyPair keyPair) { // TODO verify SPI - this.cipherRSA.init(Cipher.DECRYPT_MODE, privateKey); + cipherRSA.init(Cipher.DECRYPT_MODE, privateKey); RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic(); int keyLength = rsaPublicKey.getModulus().bitLength() / 8; @@ -484,7 +567,7 @@ public String diameterDecrypt(Message message, KeyPair keyPair) { byte[][] datas = splitByteArray(d, keyLength/* - 11*/); byte[] decryptedText = null; for (byte[] _b : datas) { - d = this.cipherRSA.doFinal(_b); + d = cipherRSA.doFinal(_b); // ---- Verify TVP from Security header ---- long t = System.currentTimeMillis()/100; // in 0.1s @@ -564,7 +647,7 @@ public String diameterDecrypt(Message message, KeyPair keyPair) { // TODO verify SPI - this.cipherRSA.init(Cipher.DECRYPT_MODE, privateKey); + cipherRSA.init(Cipher.DECRYPT_MODE, privateKey); RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic(); int keyLength = rsaPublicKey.getModulus().bitLength() / 8; @@ -572,7 +655,7 @@ public String diameterDecrypt(Message message, KeyPair keyPair) { byte[][] datas = splitByteArray(d, keyLength/* - 11*/); byte[] decryptedText = null; for (byte[] _b : datas) { - d = this.cipherRSA.doFinal(_b); + d = cipherRSA.doFinal(_b); // ---- Verify TVP from Security header ---- long t = System.currentTimeMillis()/100; // in 0.1s @@ -620,15 +703,23 @@ public String diameterDecrypt(Message message, KeyPair keyPair) { avps.removeAvpByIndex(i + _avps.size()); } catch (InvalidKeyException ex) { - java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterDecrypt InvalidKeyException"); } catch (IllegalBlockSizeException ex) { - java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterDecrypt IllegalBlockSizeException"); } catch (BadPaddingException ex) { - java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterDecrypt BadPaddingException"); } catch (AvpDataException ex) { - java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterDecrypt AvpDataException"); } catch (IOException ex) { - java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterDecrypt IOException"); + } catch (IllegalStateException ex) { + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterDecrypt IllegalStateException"); } } else if (privateKey instanceof ECPrivateKey) { logger.warn("EC algorithm not implemented"); @@ -652,6 +743,31 @@ public String diameterDecrypt(Message message, KeyPair keyPair) { */ public void diameterEncrypt_v2(Message message, PublicKey publicKey) throws InvalidKeyException { + // Encryption RSA + Cipher cipherRSA = null; + // Encryption EC + Cipher cipherAES_GCM = null; + + // Encryption RSA + try { + cipherRSA = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + cipherAES_GCM = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchProviderException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + //logger.debug("== diameterEncrypt_v2 =="); AvpSet avps = message.getAvps(); @@ -697,18 +813,18 @@ public void diameterEncrypt_v2(Message message, PublicKey publicKey) throws Inva TVP[2] = (byte) ((t >> 8) & 0xFF); TVP[3] = (byte) ((t >> 0) & 0xFF); - //this.cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); - //byte[] cipherText = this.cipherRSA.doFinal(b); + //Crypto.cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); + //byte[] cipherText = Crypto.cipherRSA.doFinal(b); RSAPublicKey rsaPublicKey = (RSAPublicKey)publicKey; - this.cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); + cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); int keyLength = rsaPublicKey.getModulus().bitLength() / 8; byte[][] datas = splitByteArray(d, keyLength - 11 - 4); byte[] cipherText = null; for (byte[] b : datas) { - cipherText = concatByteArray(cipherText, this.cipherRSA.doFinal(concatByteArray(TVP, b))); + cipherText = concatByteArray(cipherText, cipherRSA.doFinal(concatByteArray(TVP, b))); } cipherText = concatByteArray(SPI, cipherText); @@ -718,10 +834,15 @@ public void diameterEncrypt_v2(Message message, PublicKey publicKey) throws Inva avps.addAvp(AVP_ENCRYPTED_GROUPED, cipherText, false, false); } catch (IllegalBlockSizeException ex) { - java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterEncrypt_v2 IllegalBlockSizeException"); } catch (BadPaddingException ex) { - java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); - } + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterEncrypt_v2 BadPaddingException"); + } catch (IllegalStateException ex) { + //java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("diameterEncrypt_v2 IllegalStateException"); + } } else if (publicKey instanceof ECPublicKey) { logger.warn("EC Public Key algorithm not implemented"); return; @@ -744,6 +865,24 @@ public void diameterEncrypt_v2(Message message, PublicKey publicKey) throws Inva */ @Override public int tcapVerify(SccpDataMessage message, TCBeginMessage tcb, Component[] comps, PublicKey publicKey) { + + Signature signatureRSA = null; + Signature signatureECDSA = null; + + // Encryption RSA + try { + signatureRSA = Signature.getInstance("SHA256WithRSA"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + signatureECDSA = Signature.getInstance("SHA256withECDSA"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + // --------------- TCAP verify --------------- int signature_ok = 0; @@ -846,9 +985,9 @@ public int tcapVerify(SccpDataMessage message, TCBeginMessage tcb, Component[] c } if (publicKey instanceof RSAPublicKey) { - this.signatureRSA.initVerify(publicKey); - this.signatureRSA.update(dataToSign.getBytes()); - if (signatureBytes != null && this.signatureRSA.verify(signatureBytes)) { + signatureRSA.initVerify(publicKey); + signatureRSA.update(dataToSign.getBytes()); + if (signatureBytes != null && signatureRSA.verify(signatureBytes)) { signature_ok = 1; } } else if (publicKey instanceof ECPublicKey) { @@ -888,6 +1027,25 @@ public int tcapVerify(SccpDataMessage message, TCBeginMessage tcb, Component[] c */ @Override public LongMessageRuleType tcapSign(SccpDataMessage message, TCBeginMessage tcb, Component[] comps, LongMessageRuleType lmrt, KeyPair keyPair) { + + Signature signatureRSA = null; + Signature signatureECDSA = null; + + // Encryption RSA + try { + signatureRSA = Signature.getInstance("SHA256WithRSA"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + signatureECDSA = Signature.getInstance("SHA256withECDSA"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // --------------- TCAP signing --------------- LongMessageRuleType l = lmrt; @@ -963,10 +1121,10 @@ public LongMessageRuleType tcapSign(SccpDataMessage message, TCBeginMessage tcb, byte[] signatureBytes = null; // RSA if (privateKey instanceof RSAPrivateKey) { - this.signatureRSA.initSign(privateKey); + signatureRSA.initSign(privateKey); - this.signatureRSA.update(dataToSign.getBytes()); - signatureBytes = this.signatureRSA.sign(); + signatureRSA.update(dataToSign.getBytes()); + signatureBytes = signatureRSA.sign(); } // EC else if (privateKey instanceof ECPrivateKey) { @@ -1023,7 +1181,32 @@ else if (privateKey instanceof ECPrivateKey) { @Override public Pair tcapEncrypt(SccpDataMessage message, MessageFactoryImpl sccpMessageFactory, PublicKey publicKey, LongMessageRuleType lmrt) { logger.debug("TCAP Encryption for SCCP Called GT = " + message.getCalledPartyAddress().getGlobalTitle().getDigits()); - + + // Encryption RSA + Cipher cipherRSA = null; + // Encryption EC + Cipher cipherAES_GCM = null; + + // Encryption RSA + try { + cipherRSA = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + cipherAES_GCM = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchProviderException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + LongMessageRuleType l = lmrt; try { @@ -1042,14 +1225,14 @@ public Pair tcapEncrypt(SccpDataMessage me if (publicKey instanceof RSAPublicKey) { RSAPublicKey rsaPublicKey = (RSAPublicKey)publicKey; - this.cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); + cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey); int keyLength = rsaPublicKey.getModulus().bitLength() / 8; byte[][] datas = splitByteArray(message.getData(), keyLength - 11 - 4); byte[] cipherText = null; for (byte[] b : datas) { - cipherText = concatByteArray(cipherText, this.cipherRSA.doFinal(concatByteArray(TVP, b))); + cipherText = concatByteArray(cipherText, cipherRSA.doFinal(concatByteArray(TVP, b))); } cipherText = concatByteArray(SPI, cipherText); @@ -1087,6 +1270,31 @@ public Pair tcapEncrypt(SccpDataMessage me public Pair tcapDecrypt(SccpDataMessage message, MessageFactoryImpl sccpMessageFactory, KeyPair keyPair) { logger.debug("TCAP Decryption for SCCP Called GT = " + message.getCalledPartyAddress().getGlobalTitle().getDigits()); + // Encryption RSA + Cipher cipherRSA = null; + // Encryption EC + Cipher cipherAES_GCM = null; + + // Encryption RSA + try { + cipherRSA = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + + // Encryption EC + try { + cipherAES_GCM = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE"); + } catch (NoSuchAlgorithmException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchPaddingException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } catch (NoSuchProviderException ex) { + java.util.logging.Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); + } + try { // Sending XUDT message from UDT message @@ -1106,7 +1314,7 @@ public Pair tcapDecrypt(SccpDataMessage message, Messag if (privateKey instanceof RSAPrivateKey) { - this.cipherRSA.init(Cipher.DECRYPT_MODE, privateKey); + cipherRSA.init(Cipher.DECRYPT_MODE, privateKey); RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); int keyLength = rsaPublicKey.getModulus().bitLength() / 8; @@ -1116,7 +1324,7 @@ public Pair tcapDecrypt(SccpDataMessage message, Messag byte[] decryptedText = null; for (byte[] b : datas) { - byte[] d = this.cipherRSA.doFinal(b); + byte[] d = cipherRSA.doFinal(b); // ------- Verify TVP -------- long t = System.currentTimeMillis() / 100; // in 0.1s TVP[0] = (byte) ((t >> 24) & 0xFF); diff --git a/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7Firewall.java b/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7Firewall.java index 4fece2f..bdec7c4 100644 --- a/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7Firewall.java +++ b/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7Firewall.java @@ -283,6 +283,8 @@ import sigfw.connectorMThreat.ConnectorMThreatModuleRest; import com.p1sec.sigfw.SigFW_interface.FirewallRulesInterface; import java.security.interfaces.ECPublicKey; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import javafx.util.Pair; import org.mobicents.protocols.sctp.netty.NettySctpManagementImpl; import sigfw.common.Crypto; @@ -297,6 +299,9 @@ public class SS7Firewall implements ManagementEventListener, Mtp3UserPartListene private static final ParameterFactoryImpl factory = new ParameterFactoryImpl(); private static final int NETWORK_INDICATOR = 2; // used for SCCP router, just used for passive decoding private static final int SSN = 0; // used for MAP stack, just used for passive decoding + + // Executor Threads + ExecutorService threadPool = Executors.newFixedThreadPool(16); // Unit Tests flags public static boolean unitTesting = false; @@ -456,6 +461,8 @@ private void initM3UA() throws Exception { this.serverM3UAMgmt.setTransportManagement(this.sctpManagement); + // this.serverM3UAMgmt.setDeliveryMessageThreadCount(16); + this.serverM3UAMgmt.start(); this.serverM3UAMgmt.removeAllResourses(); @@ -493,6 +500,9 @@ private void initM3UA() throws Exception { this.clientM3UAMgmt.setPersistDir(persistDir); this.clientM3UAMgmt.setTransportManagement(this.sctpManagement); + + // this.clientM3UAMgmt.setDeliveryMessageThreadCount(16); + this.clientM3UAMgmt.start(); this.clientM3UAMgmt.removeAllResourses(); @@ -963,845 +973,856 @@ private void firewallMessage(Mtp3UserPart mup, Mtp3UserPart mupReturn, int opc, * @param message SCCP data message */ @Override - public void onMessage(SccpDataMessage message) { - logger.debug("[[[[[[[[[[ Sccp Message Recieved ]]]]]]]]]]"); - logger.debug(message.toString()); - - int dpc = message.getIncomingDpc(); - int opc = message.getIncomingOpc(); - int sls = message.getSls(); - int ni = message.getNetworkId(); + public void onMessage(final SccpDataMessage msg) { - Mtp3UserPart mup = this.serverM3UAMgmt; - Mtp3UserPart mupReturn = this.clientM3UAMgmt; - - - // LUA variables - HashMap lua_hmap = new HashMap(); - lua_hmap.put("sccp_calling_gt", ""); - lua_hmap.put("sccp_called_gt", ""); - lua_hmap.put("tcap_oc", ""); - lua_hmap.put("tcap_ac", ""); - lua_hmap.put("tcap_tag", ""); - lua_hmap.put("map_imsi", ""); - lua_hmap.put("map_msisdn", ""); - - for (int i = 0; i < SS7FirewallConfig.m3ua_server_remote_pc.size(); i++) { - if (dpc == Integer.parseInt(SS7FirewallConfig.m3ua_server_remote_pc.get(i))) { - mup = this.serverM3UAMgmt; - mupReturn = this.clientM3UAMgmt; - break; - } - } - for (int i = 0; i < SS7FirewallConfig.m3ua_client_remote_pc.size(); i++) { - if (dpc == Integer.parseInt(SS7FirewallConfig.m3ua_client_remote_pc.get(i))) { - mup = this.clientM3UAMgmt; - mupReturn = this.serverM3UAMgmt; - break; - } - } - - //LongMessageRule lmr = this.sccpStack.getRouter().findLongMessageRule(dpc); - LongMessageRule lmr = null; - for (Map.Entry e : this.sccpStack.getRouter().getLongMessageRules().entrySet()) { - LongMessageRule rule = e.getValue(); - if (rule.matches(dpc)) { - lmr = rule; - break; - } - } - - LongMessageRuleType lmrt = LongMessageRuleType.LONG_MESSAGE_FORBBIDEN; - if (message.getType() == SccpMessage.MESSAGE_TYPE_XUDT) { - lmrt = LongMessageRuleType.XUDT_ENABLED; - } - - // ------------- SCCP firewall ------------- - - // Calling GT whitelist and blacklist - if (message.getCallingPartyAddress() != null - && message.getCallingPartyAddress().getGlobalTitle() != null) { - lua_hmap.put("sccp_calling_gt", message.getCallingPartyAddress().getGlobalTitle().getDigits()); - - if(SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.sccp_calling_gt_whitelist, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - logger.info("============ SCCP Whitelisted Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits() + " ============"); - sendSccpMessage(mup, opc, dpc, sls, ni, lmrt, message); - return; - } - - //logger.debug("SCCP Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits()); - if(SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.sccp_calling_gt_blacklist, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { + threadPool.execute(new Runnable() { + @Override + public void run() { + + logger.debug("[[[[[[[[[[ Sccp Message Recieved ]]]]]]]]]]"); + + SccpDataMessage message = msg; + + logger.debug(message.toString()); - //logger.info("============ SCCP Blocked Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits() + " ============"); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "SCCP FW: Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits(), lua_hmap); - return; + int dpc = message.getIncomingDpc(); + int opc = message.getIncomingOpc(); + int sls = message.getSls(); + int ni = message.getNetworkId(); - } - } - - if (message.getCalledPartyAddress() != null) { - if (message.getCalledPartyAddress().getGlobalTitle() != null) { - lua_hmap.put("sccp_called_gt", message.getCalledPartyAddress().getGlobalTitle().getDigits()); - } - } - - - // ------------ TCAP decryption ------------- - if (message.getType() == SccpDataMessage.MESSAGE_TYPE_XUDT && message.getCalledPartyAddress() != null) { - if (message.getCalledPartyAddress().getGlobalTitle() != null) { - KeyPair keyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.called_gt_decryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); - if (keyPair != null) { - Pair p = crypto.tcapDecrypt(message, this.sccpMessageFactory, keyPair); - message = p.getKey(); - String r = p.getValue(); - if (!r.equals("")) { - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, r, lua_hmap); - return; + Mtp3UserPart mup = SS7Firewall.serverM3UAMgmt; + Mtp3UserPart mupReturn = SS7Firewall.clientM3UAMgmt; + + // LUA variables + HashMap lua_hmap = new HashMap(); + lua_hmap.put("sccp_calling_gt", ""); + lua_hmap.put("sccp_called_gt", ""); + lua_hmap.put("tcap_oc", ""); + lua_hmap.put("tcap_ac", ""); + lua_hmap.put("tcap_tag", ""); + lua_hmap.put("map_imsi", ""); + lua_hmap.put("map_msisdn", ""); + + for (int i = 0; i < SS7FirewallConfig.m3ua_server_remote_pc.size(); i++) { + if (dpc == Integer.parseInt(SS7FirewallConfig.m3ua_server_remote_pc.get(i))) { + mup = SS7Firewall.serverM3UAMgmt; + mupReturn = SS7Firewall.clientM3UAMgmt; + break; + } + } + for (int i = 0; i < SS7FirewallConfig.m3ua_client_remote_pc.size(); i++) { + if (dpc == Integer.parseInt(SS7FirewallConfig.m3ua_client_remote_pc.get(i))) { + mup = SS7Firewall.clientM3UAMgmt; + mupReturn = SS7Firewall.serverM3UAMgmt; + break; } } - } - } - // ------------------------------------------ - - // -------------- TCAP firewall ------------- - // TCAP - byte[] data = message.getData(); - SccpAddress localAddress = message.getCalledPartyAddress(); - SccpAddress remoteAddress = message.getCallingPartyAddress(); - long dialogId = 0; - DialogPortion dialogPortion = null; - ApplicationContextName ACN = null; - Component[] comps = null; - - // asnData - it should pass - AsnInputStream ais = new AsnInputStream(data); - - // this should have TC message tag - int tag; - try { - tag = ais.readTag(); - } catch (IOException ex) { - java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Missing TC tag", lua_hmap); - return; - } - - if (ais.getTagClass() != Tag.CLASS_APPLICATION) { - //unrecognizedPackageType(message, localAddress, remoteAddress, ais, tag, message.getNetworkId()); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Unrecognized TC tag", lua_hmap); - return; - } - dialogPortion = null; - comps = null; + //LongMessageRule lmr = this.sccpStack.getRouter().findLongMessageRule(dpc); + LongMessageRule lmr = null; + for (Map.Entry e : SS7Firewall.sccpStack.getRouter().getLongMessageRules().entrySet()) { + LongMessageRule rule = e.getValue(); + if (rule.matches(dpc)) { + lmr = rule; + break; + } + } - lua_hmap.put("tcap_tag", new Integer(tag).toString()); + LongMessageRuleType lmrt = LongMessageRuleType.LONG_MESSAGE_FORBBIDEN; + if (message.getType() == SccpMessage.MESSAGE_TYPE_XUDT) { + lmrt = LongMessageRuleType.XUDT_ENABLED; + } - TCContinueMessage tcm = null; - TCBeginMessage tcb = null; - TCEndMessage teb = null; - TCAbortMessage tub = null; - TCUniMessage tcuni; - - switch (tag) { - // continue first, usually we will get more of those. small perf - // boost - case TCContinueMessage._TAG: - try { - tcm = TcapFactory.createTCContinueMessage(ais); - } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { - logger.debug("ParseException when parsing TCContinueMessage: " + e.toString(), e); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCContinueMessage", lua_hmap); - return; - } + // ------------- SCCP firewall ------------- - // TID - dialogId = Utils.decodeTransactionId(tcm.getDestinationTransactionId()); + // Calling GT whitelist and blacklist + if (message.getCallingPartyAddress() != null + && message.getCallingPartyAddress().getGlobalTitle() != null) { + lua_hmap.put("sccp_calling_gt", message.getCallingPartyAddress().getGlobalTitle().getDigits()); - // Application Context - dialogPortion = tcm.getDialogPortion(); + if(SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.sccp_calling_gt_whitelist, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { + logger.info("============ SCCP Whitelisted Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits() + " ============"); + sendSccpMessage(mup, opc, dpc, sls, ni, lmrt, message); + return; + } - // Operation Code - comps = tcm.getComponent(); + //logger.debug("SCCP Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits()); + if(SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.sccp_calling_gt_blacklist, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - break; + //logger.info("============ SCCP Blocked Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits() + " ============"); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "SCCP FW: Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits(), lua_hmap); + return; - case TCBeginMessage._TAG: - try { - tcb = TcapFactory.createTCBeginMessage(ais); - } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { - logger.debug("ParseException when parsing TCBeginMessage: " + e.toString(), e); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCBeginMessage", lua_hmap); - return; - } - if (tcb.getDialogPortion() != null && tcb.getDialogPortion().getDialogAPDU() != null - && tcb.getDialogPortion().getDialogAPDU() instanceof DialogRequestAPDUImpl) { - DialogRequestAPDUImpl dlg = (DialogRequestAPDUImpl) tcb.getDialogPortion().getDialogAPDU(); - if (!dlg.getProtocolVersion().isSupportedVersion()) { - logger.debug("Unsupported protocol version of has been received when parsing TCBeginMessage"); - //this.sendProviderAbort(DialogServiceProviderType.NoCommonDialogPortion, tcb.getOriginatingTransactionId(), remoteAddress, localAddress, - // message.getSls(), dlg.getApplicationContextName(), message.getNetworkId()); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Unsupported protocol version of has been received when parsing TCBeginMessage", lua_hmap); - return; + } } - } - - // TID - dialogId = Utils.decodeTransactionId(tcb.getOriginatingTransactionId()); - - // Application Context - dialogPortion = tcb.getDialogPortion(); - - // Operation Code - comps = tcb.getComponent(); + if (message.getCalledPartyAddress() != null) { + if (message.getCalledPartyAddress().getGlobalTitle() != null) { + lua_hmap.put("sccp_called_gt", message.getCalledPartyAddress().getGlobalTitle().getDigits()); + } + } - // --------------- TCAP signature --------------- - if (comps != null) { - if (message.getCallingPartyAddress() != null) { - if (message.getCallingPartyAddress().getGlobalTitle() != null) { - // --------------- TCAP verify --------------- - int signature_ok = -1; // no key - PublicKey publicKey = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.calling_gt_verify, message.getCallingPartyAddress().getGlobalTitle().getDigits()); - if (publicKey != null) { - signature_ok = crypto.tcapVerify(message, tcb, comps, publicKey) ; - if (signature_ok == 0) { - // Drop not correctly signed messages - //logger.info("============ Wrong TCAP signature, message blocked. Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits() + " ============"); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Wrong TCAP signature", lua_hmap); + // ------------ TCAP decryption ------------- + if (message.getType() == SccpDataMessage.MESSAGE_TYPE_XUDT && message.getCalledPartyAddress() != null) { + if (message.getCalledPartyAddress().getGlobalTitle() != null) { + KeyPair keyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.called_gt_decryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); + if (keyPair != null) { + Pair p = crypto.tcapDecrypt(message, SS7Firewall.sccpMessageFactory, keyPair); + message = p.getKey(); + String r = p.getValue(); + if (!r.equals("")) { + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, r, lua_hmap); return; } } - // -------------------------------------------- } } - } - // ------------------------------------------ + // ------------------------------------------ + + // -------------- TCAP firewall ------------- + // TCAP + byte[] data = message.getData(); + SccpAddress localAddress = message.getCalledPartyAddress(); + SccpAddress remoteAddress = message.getCallingPartyAddress(); + long dialogId = 0; + DialogPortion dialogPortion = null; + ApplicationContextName ACN = null; + Component[] comps = null; + + // asnData - it should pass + AsnInputStream ais = new AsnInputStream(data); + + // this should have TC message tag + int tag; + try { + tag = ais.readTag(); + } catch (IOException ex) { + java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Missing TC tag", lua_hmap); + return; + } - break; + if (ais.getTagClass() != Tag.CLASS_APPLICATION) { + //unrecognizedPackageType(message, localAddress, remoteAddress, ais, tag, message.getNetworkId()); - case TCEndMessage._TAG: - try { - teb = TcapFactory.createTCEndMessage(ais); - } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { - logger.debug("ParseException when parsing TCEndMessage: " + e.toString(), e); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCEndMessage", lua_hmap); - return; - } + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Unrecognized TC tag", lua_hmap); + return; + } - // TID - dialogId = Utils.decodeTransactionId(teb.getDestinationTransactionId()); - - // Application Context - dialogPortion = teb.getDialogPortion(); - - // Operation Code - comps = teb.getComponent(); + dialogPortion = null; + comps = null; - break; + lua_hmap.put("tcap_tag", new Integer(tag).toString()); - case TCAbortMessage._TAG: - try { - tub = TcapFactory.createTCAbortMessage(ais); - } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { - logger.debug("ParseException when parsing TCAbortMessage: " + e.toString(), e); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCAbortMessage", lua_hmap); - return; - } + TCContinueMessage tcm = null; + TCBeginMessage tcb = null; + TCEndMessage teb = null; + TCAbortMessage tub = null; + TCUniMessage tcuni; - // TID - dialogId = Utils.decodeTransactionId(tub.getDestinationTransactionId()); - - // Application Context - dialogPortion = tub.getDialogPortion(); + switch (tag) { + // continue first, usually we will get more of those. small perf + // boost + case TCContinueMessage._TAG: + try { + tcm = TcapFactory.createTCContinueMessage(ais); + } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { + logger.debug("ParseException when parsing TCContinueMessage: " + e.toString(), e); - break; + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCContinueMessage", lua_hmap); + return; + } - case TCUniMessage._TAG: - try { - tcuni = TcapFactory.createTCUniMessage(ais); - } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { - logger.debug("ParseException when parsing TCUniMessage: " + e.toString(), e); - - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCUniMessage", lua_hmap); - return; - } - - // Application Context - dialogPortion = tcuni.getDialogPortion(); - - // Operation Code - comps = tcuni.getComponent(); + // TID + dialogId = Utils.decodeTransactionId(tcm.getDestinationTransactionId()); - break; + // Application Context + dialogPortion = tcm.getDialogPortion(); - default: - //unrecognizedPackageType(message, localAddress, remoteAddress, ais, tag, message.getNetworkId()); - break; - } + // Operation Code + comps = tcm.getComponent(); + break; - // Application Context - if (dialogPortion != null) { - // this should not be null.... - DialogAPDU apdu = dialogPortion.getDialogAPDU(); - if (apdu.getType() == DialogAPDUType.Response) { - DialogResponseAPDU responseAPDU = (DialogResponseAPDU) apdu; - ACN = responseAPDU.getApplicationContextName(); - } else if (apdu.getType() == DialogAPDUType.Request) { - DialogRequestAPDU requestAPDU = (DialogRequestAPDU) apdu; - ACN = requestAPDU.getApplicationContextName(); - } - - if (ACN != null) { - lua_hmap.put("tcap_ac", ((ApplicationContextNameImpl)ACN).getStringValue()); - } - } + case TCBeginMessage._TAG: + try { + tcb = TcapFactory.createTCBeginMessage(ais); + } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { + logger.debug("ParseException when parsing TCBeginMessage: " + e.toString(), e); - // ---------- TCAP firewall ---------- - // TCAP components - if (comps != null) { - for (Component comp : comps) { - if (comp == null) { - continue; - } - - OperationCodeImpl oc; - - switch (comp.getType()) { - case Invoke: - Invoke inv = (Invoke) comp; + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCBeginMessage", lua_hmap); + return; + } + if (tcb.getDialogPortion() != null && tcb.getDialogPortion().getDialogAPDU() != null + && tcb.getDialogPortion().getDialogAPDU() instanceof DialogRequestAPDUImpl) { + DialogRequestAPDUImpl dlg = (DialogRequestAPDUImpl) tcb.getDialogPortion().getDialogAPDU(); + if (!dlg.getProtocolVersion().isSupportedVersion()) { + logger.debug("Unsupported protocol version of has been received when parsing TCBeginMessage"); + //this.sendProviderAbort(DialogServiceProviderType.NoCommonDialogPortion, tcb.getOriginatingTransactionId(), remoteAddress, localAddress, + // message.getSls(), dlg.getApplicationContextName(), message.getNetworkId()); + + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Unsupported protocol version of has been received when parsing TCBeginMessage", lua_hmap); + return; + } + } - // Operation Code - oc = (OperationCodeImpl) inv.getOperationCode(); - - // Encryption Autodiscovery Sending Result - // Only targeting HPLMN - if (oc.getLocalOperationCode() == OC_AUTO_ENCRYPTION - && SS7FirewallConfig.encryption_autodiscovery.equals("true") - && SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) - && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - - KeyPair myKeyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.called_gt_decryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); - String key = SS7FirewallConfig.simpleWildcardKeyFind(SS7FirewallConfig.called_gt_decryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); - if (myKeyPair != null) { - - - TCEndMessage t = TcapFactory.createTCEndMessage(); - - - t.setDestinationTransactionId(Utils.encodeTransactionId(dialogId)); - // Create Dialog Portion - DialogPortion dp = TcapFactory.createDialogPortion(); - - dp.setOid(true); - dp.setOidValue(new long[] { 0, 0, 17, 773, 1, 1, 1 }); - - dp.setAsn(true); - - DialogRequestAPDUImpl diRequestAPDUImpl = new DialogRequestAPDUImpl(); - - diRequestAPDUImpl.setApplicationContextName(ACN); - diRequestAPDUImpl.setDoNotSendProtocolVersion(true); - - - dp.setDialogAPDU(diRequestAPDUImpl); - - t.setDialogPortion(dp); - - - - Component[] c = new Component[1]; - - c[0] = new ReturnResultLastImpl(); - ((ReturnResultLastImpl)c[0]).setInvokeId(1l); - - oc.setLocalOperationCode(oc.getLocalOperationCode()); - ((ReturnResultLastImpl)c[0]).setOperationCode(oc); - - - // Capabilities - // TODO - Parameter p1 = TcapFactory.createParameter(); - p1.setTagClass(Tag.CLASS_PRIVATE); - p1.setPrimitive(true); - p1.setTag(Tag.STRING_OCTET); - p1.setData("Av1".getBytes()); - - // GT prefix - Parameter p2 = TcapFactory.createParameter(); - p2.setTagClass(Tag.CLASS_PRIVATE); - p2.setPrimitive(true); - p2.setTag(Tag.STRING_OCTET); - byte[] d2 = key.getBytes(); - p2.setData(d2); - - // Public key type - String publicKeyType = ""; - if (myKeyPair.getPublic() instanceof RSAPublicKey) { - publicKeyType = "RSA"; - } else if (myKeyPair.getPublic() instanceof ECPublicKey) { - publicKeyType = "EC"; - } - Parameter p3 = TcapFactory.createParameter(); - p3.setTagClass(Tag.CLASS_PRIVATE); - p3.setPrimitive(true); - p3.setTag(Tag.STRING_OCTET); - p3.setData(publicKeyType.getBytes()); - - // Public key - Parameter p4 = TcapFactory.createParameter(); - p4.setTagClass(Tag.CLASS_PRIVATE); - p4.setPrimitive(true); - p4.setTag(Tag.STRING_OCTET); - byte[] d4 = myKeyPair.getPublic().getEncoded(); - p4.setData(d4); - - Parameter p = TcapFactory.createParameter(); - p.setTagClass(Tag.CLASS_UNIVERSAL); - p.setTag(0x04); - p.setParameters(new Parameter[] { p1, p2, p3, p4}); - ((ReturnResultLastImpl)c[0]).setParameter(p); + // TID + dialogId = Utils.decodeTransactionId(tcb.getOriginatingTransactionId()); - + // Application Context + dialogPortion = tcb.getDialogPortion(); - t.setComponent(c); - AsnOutputStream aos = new AsnOutputStream(); - try { - t.encode(aos); - } catch (EncodeException ex) { - java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + + // Operation Code + comps = tcb.getComponent(); + + // --------------- TCAP signature --------------- + if (comps != null) { + if (message.getCallingPartyAddress() != null) { + if (message.getCallingPartyAddress().getGlobalTitle() != null) { + // --------------- TCAP verify --------------- + int signature_ok = -1; // no key + PublicKey publicKey = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.calling_gt_verify, message.getCallingPartyAddress().getGlobalTitle().getDigits()); + if (publicKey != null) { + signature_ok = crypto.tcapVerify(message, tcb, comps, publicKey) ; + if (signature_ok == 0) { + // Drop not correctly signed messages + //logger.info("============ Wrong TCAP signature, message blocked. Calling GT = " + message.getCallingPartyAddress().getGlobalTitle().getDigits() + " ============"); + + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: Wrong TCAP signature", lua_hmap); + return; + } + } + // -------------------------------------------- } + } + } + // ------------------------------------------ - byte[] _d = aos.toByteArray(); + break; - LongMessageRuleType l = lmrt; - SccpDataMessage m = this.sccpMessageFactory.createDataMessageClass0(message.getCallingPartyAddress(), message.getCalledPartyAddress(), message.getData(), message.getOriginLocalSsn(), false, null, null); - m.setData(_d); + case TCEndMessage._TAG: + try { + teb = TcapFactory.createTCEndMessage(ais); + } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { + logger.debug("ParseException when parsing TCEndMessage: " + e.toString(), e); - logger.info("============ Encryption Autodiscovery Sending Result ============ "); - - // Use XUDT if required - if (m.getData().length >= 240) { - l = LongMessageRuleType.XUDT_ENABLED; - } - sendSccpMessage(mupReturn, dpc, opc, sls, ni, l, m); - return; - } - + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCEndMessage", lua_hmap); + return; } - // TCAP Cat1 filtering - if (oc != null) { - //logger.debug("TCAP OC = " + oc.getStringValue()); - lua_hmap.put("tcap_oc", oc.getStringValue()); + // TID + dialogId = Utils.decodeTransactionId(teb.getDestinationTransactionId()); - if(SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.tcap_oc_blacklist, oc.getStringValue())) { - //logger.info("============ TCAP Blocked Operation Code = " + oc.getStringValue() + " ============"); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW (Cat1): OC = " + oc.getStringValue(), lua_hmap); - return; - } + // Application Context + dialogPortion = teb.getDialogPortion(); + + // Operation Code + comps = teb.getComponent(); + + break; + + case TCAbortMessage._TAG: + try { + tub = TcapFactory.createTCAbortMessage(ais); + } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { + logger.debug("ParseException when parsing TCAbortMessage: " + e.toString(), e); + + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCAbortMessage", lua_hmap); + return; } - - // Drop if ACN null for TCAP Begin - if (tag == TCBeginMessage._TAG && ACN == null) { - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW (Cat1): Missing AC", lua_hmap); + + // TID + dialogId = Utils.decodeTransactionId(tub.getDestinationTransactionId()); + + // Application Context + dialogPortion = tub.getDialogPortion(); + + break; + + case TCUniMessage._TAG: + try { + tcuni = TcapFactory.createTCUniMessage(ais); + } catch (org.mobicents.protocols.ss7.tcap.asn.ParseException e) { + logger.debug("ParseException when parsing TCUniMessage: " + e.toString(), e); + + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW: ParseException when parsing TCUniMessage", lua_hmap); return; } - // ---------- MAP decoding ---------- - String imsi = null; - - if (oc != null - && message.getCalledPartyAddress() != null && message.getCalledPartyAddress().getGlobalTitle() != null && message.getCalledPartyAddress().getGlobalTitle().getDigits() != null - && message.getCallingPartyAddress() != null && message.getCallingPartyAddress().getGlobalTitle() != null && message.getCallingPartyAddress().getGlobalTitle().getDigits() != null) { - // Optimization, decode MAP only if towards HPLMN and not originated from HPLMN - if (SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) - && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - - Parameter parameter = inv.getParameter(); - if (parameter != null) { - byte[] buf = parameter.getData(); - AsnInputStream map_ais = new AsnInputStream(buf); - - // cancelLocation - if (oc.getStringValue().equals("3")) { - CancelLocationRequestImpl ind = new CancelLocationRequestImpl(MAPApplicationContext.getProtocolVersion(ACN.getOid())); - try { - ind.decodeData(map_ais, buf.length); - } catch (MAPParsingComponentException ex) { - //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); - return; - } - ind.setInvokeId(inv.getInvokeId()); + // Application Context + dialogPortion = tcuni.getDialogPortion(); + + // Operation Code + comps = tcuni.getComponent(); + + break; + + default: + //unrecognizedPackageType(message, localAddress, remoteAddress, ais, tag, message.getNetworkId()); + break; + } + - if (((CancelLocationRequestImpl)ind).getImsi() != null) { - imsi = ((CancelLocationRequestImpl)ind).getImsi().getData(); - logger.debug("MAP CL IMSI = " + imsi); - lua_hmap.put("map_imsi", imsi); + // Application Context + if (dialogPortion != null) { + // this should not be null.... + DialogAPDU apdu = dialogPortion.getDialogAPDU(); + if (apdu.getType() == DialogAPDUType.Response) { + DialogResponseAPDU responseAPDU = (DialogResponseAPDU) apdu; + ACN = responseAPDU.getApplicationContextName(); + } else if (apdu.getType() == DialogAPDUType.Request) { + DialogRequestAPDU requestAPDU = (DialogRequestAPDU) apdu; + ACN = requestAPDU.getApplicationContextName(); + } + + if (ACN != null) { + lua_hmap.put("tcap_ac", ((ApplicationContextNameImpl)ACN).getStringValue()); + } + } + + // ---------- TCAP firewall ---------- + // TCAP components + if (comps != null) { + for (Component comp : comps) { + if (comp == null) { + continue; + } + + OperationCodeImpl oc; + + switch (comp.getType()) { + case Invoke: + Invoke inv = (Invoke) comp; + + // Operation Code + oc = (OperationCodeImpl) inv.getOperationCode(); + + // Encryption Autodiscovery Sending Result + // Only targeting HPLMN + if (oc.getLocalOperationCode() == OC_AUTO_ENCRYPTION + && SS7FirewallConfig.encryption_autodiscovery.equals("true") + && SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) + && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { + + KeyPair myKeyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.called_gt_decryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); + String key = SS7FirewallConfig.simpleWildcardKeyFind(SS7FirewallConfig.called_gt_decryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); + if (myKeyPair != null) { + + + TCEndMessage t = TcapFactory.createTCEndMessage(); + + + t.setDestinationTransactionId(Utils.encodeTransactionId(dialogId)); + // Create Dialog Portion + DialogPortion dp = TcapFactory.createDialogPortion(); + + dp.setOid(true); + dp.setOidValue(new long[] { 0, 0, 17, 773, 1, 1, 1 }); + + dp.setAsn(true); + + DialogRequestAPDUImpl diRequestAPDUImpl = new DialogRequestAPDUImpl(); + + diRequestAPDUImpl.setApplicationContextName(ACN); + diRequestAPDUImpl.setDoNotSendProtocolVersion(true); + + + dp.setDialogAPDU(diRequestAPDUImpl); + + t.setDialogPortion(dp); + + + + Component[] c = new Component[1]; + + c[0] = new ReturnResultLastImpl(); + ((ReturnResultLastImpl)c[0]).setInvokeId(1l); + + oc.setLocalOperationCode(oc.getLocalOperationCode()); + ((ReturnResultLastImpl)c[0]).setOperationCode(oc); + + + // Capabilities + // TODO + Parameter p1 = TcapFactory.createParameter(); + p1.setTagClass(Tag.CLASS_PRIVATE); + p1.setPrimitive(true); + p1.setTag(Tag.STRING_OCTET); + p1.setData("Av1".getBytes()); + + // GT prefix + Parameter p2 = TcapFactory.createParameter(); + p2.setTagClass(Tag.CLASS_PRIVATE); + p2.setPrimitive(true); + p2.setTag(Tag.STRING_OCTET); + byte[] d2 = key.getBytes(); + p2.setData(d2); + + // Public key type + String publicKeyType = ""; + if (myKeyPair.getPublic() instanceof RSAPublicKey) { + publicKeyType = "RSA"; + } else if (myKeyPair.getPublic() instanceof ECPublicKey) { + publicKeyType = "EC"; } - } - // provideRoamingNumber - if (oc.getStringValue().equals("4")) { - ProvideRoamingNumberRequestImpl ind = new ProvideRoamingNumberRequestImpl(MAPApplicationContext.getProtocolVersion(ACN.getOid())); + Parameter p3 = TcapFactory.createParameter(); + p3.setTagClass(Tag.CLASS_PRIVATE); + p3.setPrimitive(true); + p3.setTag(Tag.STRING_OCTET); + p3.setData(publicKeyType.getBytes()); + + // Public key + Parameter p4 = TcapFactory.createParameter(); + p4.setTagClass(Tag.CLASS_PRIVATE); + p4.setPrimitive(true); + p4.setTag(Tag.STRING_OCTET); + byte[] d4 = myKeyPair.getPublic().getEncoded(); + p4.setData(d4); + + Parameter p = TcapFactory.createParameter(); + p.setTagClass(Tag.CLASS_UNIVERSAL); + p.setTag(0x04); + p.setParameters(new Parameter[] { p1, p2, p3, p4}); + ((ReturnResultLastImpl)c[0]).setParameter(p); + + + + t.setComponent(c); + AsnOutputStream aos = new AsnOutputStream(); try { - ind.decodeData(map_ais, buf.length); - } catch (MAPParsingComponentException ex) { - //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); - return; + t.encode(aos); + } catch (EncodeException ex) { + java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); } - ind.setInvokeId(inv.getInvokeId()); - if (((ProvideRoamingNumberRequestImpl)ind).getImsi() != null) { - imsi = ((ProvideRoamingNumberRequestImpl)ind).getImsi().getData(); - logger.debug("MAP PRN IMSI = " + imsi); - lua_hmap.put("map_imsi", imsi); + byte[] _d = aos.toByteArray(); + + LongMessageRuleType l = lmrt; + SccpDataMessage m = SS7Firewall.sccpMessageFactory.createDataMessageClass0(message.getCallingPartyAddress(), message.getCalledPartyAddress(), message.getData(), message.getOriginLocalSsn(), false, null, null); + m.setData(_d); + + logger.info("============ Encryption Autodiscovery Sending Result ============ "); + + // Use XUDT if required + if (m.getData().length >= 240) { + l = LongMessageRuleType.XUDT_ENABLED; } + sendSccpMessage(mupReturn, dpc, opc, sls, ni, l, m); + return; } - // insertSubscriberData - if (oc.getStringValue().equals("7")) { - InsertSubscriberDataRequestImpl ind = new InsertSubscriberDataRequestImpl(MAPApplicationContext.getProtocolVersion(ACN.getOid())); - try { - ind.decodeData(map_ais, buf.length); - } catch (MAPParsingComponentException ex) { - //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); - return; - } - ind.setInvokeId(inv.getInvokeId()); - if (((InsertSubscriberDataRequestImpl)ind).getImsi() != null) { - imsi = ((InsertSubscriberDataRequestImpl)ind).getImsi().getData(); - logger.debug("MAP ISD IMSI = " + imsi); - lua_hmap.put("map_imsi", imsi); - } + } + + // TCAP Cat1 filtering + if (oc != null) { + //logger.debug("TCAP OC = " + oc.getStringValue()); + lua_hmap.put("tcap_oc", oc.getStringValue()); + + if(SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.tcap_oc_blacklist, oc.getStringValue())) { + //logger.info("============ TCAP Blocked Operation Code = " + oc.getStringValue() + " ============"); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW (Cat1): OC = " + oc.getStringValue(), lua_hmap); + return; } - // deleteSubscriberData - if (oc.getStringValue().equals("8")) { - DeleteSubscriberDataRequestImpl ind = new DeleteSubscriberDataRequestImpl(); - try { - ind.decodeData(map_ais, buf.length); - } catch (MAPParsingComponentException ex) { - //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); - return; - } - ind.setInvokeId(inv.getInvokeId()); + } - if (((DeleteSubscriberDataRequestImpl)ind).getImsi() != null) { - imsi = ((DeleteSubscriberDataRequestImpl)ind).getImsi().getData(); - logger.debug("MAP DSD IMSI = " + imsi); - lua_hmap.put("map_imsi", imsi); + // Drop if ACN null for TCAP Begin + if (tag == TCBeginMessage._TAG && ACN == null) { + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "TCAP FW (Cat1): Missing AC", lua_hmap); + return; + } + + // ---------- MAP decoding ---------- + String imsi = null; + + if (oc != null + && message.getCalledPartyAddress() != null && message.getCalledPartyAddress().getGlobalTitle() != null && message.getCalledPartyAddress().getGlobalTitle().getDigits() != null + && message.getCallingPartyAddress() != null && message.getCallingPartyAddress().getGlobalTitle() != null && message.getCallingPartyAddress().getGlobalTitle().getDigits() != null) { + // Optimization, decode MAP only if towards HPLMN and not originated from HPLMN + if (SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) + && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { + + Parameter parameter = inv.getParameter(); + if (parameter != null) { + byte[] buf = parameter.getData(); + AsnInputStream map_ais = new AsnInputStream(buf); + + // cancelLocation + if (oc.getStringValue().equals("3")) { + CancelLocationRequestImpl ind = new CancelLocationRequestImpl(MAPApplicationContext.getProtocolVersion(ACN.getOid())); + try { + ind.decodeData(map_ais, buf.length); + } catch (MAPParsingComponentException ex) { + //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); + return; + } + ind.setInvokeId(inv.getInvokeId()); + + if (((CancelLocationRequestImpl)ind).getImsi() != null) { + imsi = ((CancelLocationRequestImpl)ind).getImsi().getData(); + logger.debug("MAP CL IMSI = " + imsi); + lua_hmap.put("map_imsi", imsi); + } + } + // provideRoamingNumber + if (oc.getStringValue().equals("4")) { + ProvideRoamingNumberRequestImpl ind = new ProvideRoamingNumberRequestImpl(MAPApplicationContext.getProtocolVersion(ACN.getOid())); + try { + ind.decodeData(map_ais, buf.length); + } catch (MAPParsingComponentException ex) { + //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); + return; + } + ind.setInvokeId(inv.getInvokeId()); + + if (((ProvideRoamingNumberRequestImpl)ind).getImsi() != null) { + imsi = ((ProvideRoamingNumberRequestImpl)ind).getImsi().getData(); + logger.debug("MAP PRN IMSI = " + imsi); + lua_hmap.put("map_imsi", imsi); + } + } + // insertSubscriberData + if (oc.getStringValue().equals("7")) { + InsertSubscriberDataRequestImpl ind = new InsertSubscriberDataRequestImpl(MAPApplicationContext.getProtocolVersion(ACN.getOid())); + try { + ind.decodeData(map_ais, buf.length); + } catch (MAPParsingComponentException ex) { + //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); + return; + } + ind.setInvokeId(inv.getInvokeId()); + + if (((InsertSubscriberDataRequestImpl)ind).getImsi() != null) { + imsi = ((InsertSubscriberDataRequestImpl)ind).getImsi().getData(); + logger.debug("MAP ISD IMSI = " + imsi); + lua_hmap.put("map_imsi", imsi); + } + } + // deleteSubscriberData + if (oc.getStringValue().equals("8")) { + DeleteSubscriberDataRequestImpl ind = new DeleteSubscriberDataRequestImpl(); + try { + ind.decodeData(map_ais, buf.length); + } catch (MAPParsingComponentException ex) { + //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); + return; + } + ind.setInvokeId(inv.getInvokeId()); + + if (((DeleteSubscriberDataRequestImpl)ind).getImsi() != null) { + imsi = ((DeleteSubscriberDataRequestImpl)ind).getImsi().getData(); + logger.debug("MAP DSD IMSI = " + imsi); + lua_hmap.put("map_imsi", imsi); + } + } + // provideSubscriberInfo + if (oc.getStringValue().equals("70")) { + ProvideSubscriberInfoRequestImpl ind = new ProvideSubscriberInfoRequestImpl(); + try { + ind.decodeData(map_ais, buf.length); + } catch (MAPParsingComponentException ex) { + //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); + return; + } + ind.setInvokeId(inv.getInvokeId()); + + if (((ProvideSubscriberInfoRequestImpl)ind).getImsi() != null) { + imsi = ((ProvideSubscriberInfoRequestImpl)ind).getImsi().getData(); + logger.debug("MAP PSI IMSI = " + imsi); + lua_hmap.put("map_imsi", imsi); + } + } } } - // provideSubscriberInfo - if (oc.getStringValue().equals("70")) { - ProvideSubscriberInfoRequestImpl ind = new ProvideSubscriberInfoRequestImpl(); - try { - ind.decodeData(map_ais, buf.length); - } catch (MAPParsingComponentException ex) { - //java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Failed decoding, OC = " + oc.getStringValue(), lua_hmap); - return; + } + // ---------------------------------- + + // ---------- MAP firewall ---------- + // MAP Cat2 filtering + if (oc != null) { + if (SS7FirewallConfig.map_cat2_oc_blacklist.containsKey(oc.getStringValue())) { + // If towards HPLMN and not originated from HPLMN + if (SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) + && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { + + // Drop if message targets IMSI in HPLMN + if (imsi != null) { + // IMSI prefix check + for (String imsi_prefix: SS7FirewallConfig.hplmn_imsi.keySet()) { + if (imsi.startsWith(imsi_prefix)) { + // logger.info("============ MAP Cat2 Blocked Operation Code = " + oc.getStringValue() + " ============"); + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW (Cat2): OC = " + oc.getStringValue(), lua_hmap); + return; + } + } + } } - ind.setInvokeId(inv.getInvokeId()); - if (((ProvideSubscriberInfoRequestImpl)ind).getImsi() != null) { - imsi = ((ProvideSubscriberInfoRequestImpl)ind).getImsi().getData(); - logger.debug("MAP PSI IMSI = " + imsi); - lua_hmap.put("map_imsi", imsi); - } } } - } - } - // ---------------------------------- - - // ---------- MAP firewall ---------- - // MAP Cat2 filtering - if (oc != null) { - if (SS7FirewallConfig.map_cat2_oc_blacklist.containsKey(oc.getStringValue())) { - // If towards HPLMN and not originated from HPLMN - if (SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) - && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - - // Drop if message targets IMSI in HPLMN - if (imsi != null) { - // IMSI prefix check - for (String imsi_prefix: SS7FirewallConfig.hplmn_imsi.keySet()) { - if (imsi.startsWith(imsi_prefix)) { - // logger.info("============ MAP Cat2 Blocked Operation Code = " + oc.getStringValue() + " ============"); - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW (Cat2): OC = " + oc.getStringValue(), lua_hmap); - return; + // ---------------------------------- + break; + case ReturnResult: + break; + case ReturnResultLast: + ReturnResultLast result = (ReturnResultLast) comp; + + // Operation Code + oc = (OperationCodeImpl) result.getOperationCode(); + + // Encryption Autodiscovery Receiving Result + // Only targeting HPLMN + + if (oc.getLocalOperationCode() == OC_AUTO_ENCRYPTION + && SS7FirewallConfig.encryption_autodiscovery.equals("true") + && message.getCalledPartyAddress() != null && message.getCalledPartyAddress().getGlobalTitle() != null && message.getCalledPartyAddress().getGlobalTitle().getDigits() != null + && SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) + && message.getCallingPartyAddress() != null && message.getCallingPartyAddress().getGlobalTitle() != null && message.getCallingPartyAddress().getGlobalTitle().getDigits() != null + && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { + + logger.info("============ Encryption Autodiscovery Receiving Result ============ "); + + if (encryption_autodiscovery_sessions.containsKey(message.getCallingPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length()))) + && encryption_autodiscovery_sessions.get(message.getCallingPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length()))) == dialogId) { + + // do not remove the key and wait for expiration to not send too many autodiscovery request messages + //encryption_autodiscovery_sessions.remove(message.getCallingPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length()))); + + Parameter p = result.getParameter(); + Parameter[] params = p.getParameters(); + if (params != null && params.length >= 2) { + + // Capabilities + // TODO + Parameter p1 = params[0]; + + // GT prefix + Parameter p2 = params[1]; + byte[] d2 = p2.getData(); + String called_gt = new String(d2); + + // Public key type + Parameter p3 = params[2]; + byte[] d3 = p3.getData(); + String publicKeyType = new String(d3); + + // Public key + Parameter p4 = params[3]; + byte[] d4 = p4.getData(); + // TODO add method into config to add public key + byte[] publicKeyBytes = d4; + try { + X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes); + PublicKey publicKey; + publicKey = keyFactoryRSA.generatePublic(pubKeySpec); + SS7FirewallConfig.called_gt_encryption.put(called_gt, publicKey); + } catch (InvalidKeySpecException ex) { + java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); } + } + } - } - } - } - // ---------------------------------- - break; - case ReturnResult: - break; - case ReturnResultLast: - ReturnResultLast result = (ReturnResultLast) comp; - - // Operation Code - oc = (OperationCodeImpl) result.getOperationCode(); - - // Encryption Autodiscovery Receiving Result - // Only targeting HPLMN - - if (oc.getLocalOperationCode() == OC_AUTO_ENCRYPTION - && SS7FirewallConfig.encryption_autodiscovery.equals("true") - && message.getCalledPartyAddress() != null && message.getCalledPartyAddress().getGlobalTitle() != null && message.getCalledPartyAddress().getGlobalTitle().getDigits() != null - && SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) - && message.getCallingPartyAddress() != null && message.getCallingPartyAddress().getGlobalTitle() != null && message.getCallingPartyAddress().getGlobalTitle().getDigits() != null - && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - - logger.info("============ Encryption Autodiscovery Receiving Result ============ "); - - if (encryption_autodiscovery_sessions.containsKey(message.getCallingPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length()))) - && encryption_autodiscovery_sessions.get(message.getCallingPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length()))) == dialogId) { - - // do not remove the key and wait for expiration to not send too many autodiscovery request messages - //encryption_autodiscovery_sessions.remove(message.getCallingPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length()))); - - Parameter p = result.getParameter(); - Parameter[] params = p.getParameters(); - if (params != null && params.length >= 2) { - - // Capabilities - // TODO - Parameter p1 = params[0]; - - // GT prefix - Parameter p2 = params[1]; - byte[] d2 = p2.getData(); - String called_gt = new String(d2); - - // Public key type - Parameter p3 = params[2]; - byte[] d3 = p3.getData(); - String publicKeyType = new String(d3); - - // Public key - Parameter p4 = params[3]; - byte[] d4 = p4.getData(); - // TODO add method into config to add public key - byte[] publicKeyBytes = d4; - try { - X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes); - PublicKey publicKey; - publicKey = keyFactoryRSA.generatePublic(pubKeySpec); - SS7FirewallConfig.called_gt_encryption.put(called_gt, publicKey); - } catch (InvalidKeySpecException ex) { - java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + // do not forward message + return; + } + + + + break; + case ReturnError: + ReturnError re = (ReturnError) comp; + ErrorCodeImpl ec = (ErrorCodeImpl) re.getErrorCode(); + if (ec != null) { + } + break; + case Reject: + Reject rej = (Reject) comp; + if (!rej.isLocalOriginated()) { + ProblemImpl prob = (ProblemImpl) rej.getProblem(); + if (prob != null) { } - } - + break; } - - // do not forward message - return; - } - - - - break; - case ReturnError: - ReturnError re = (ReturnError) comp; - ErrorCodeImpl ec = (ErrorCodeImpl) re.getErrorCode(); - if (ec != null) { } - break; - case Reject: - Reject rej = (Reject) comp; - if (!rej.isLocalOriginated()) { - ProblemImpl prob = (ProblemImpl) rej.getProblem(); - if (prob != null) { - } - } - break; } - } - } - - // -------------- Externel Firewall rules ----------------- - if (externalFirewallRules.ss7FirewallRules(message) == false) { - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "SS7 FW: Match with Externel Firewall rules", lua_hmap); - return; - } - - // -------------- LUA rules ----------------- - ScriptEngineManager mgr = new ScriptEngineManager(); - ScriptEngine eng = mgr.getEngineByName("luaj"); - for (String key : lua_hmap.keySet()) { - eng.put(key, lua_hmap.get(key)); - } - boolean lua_match = false; - int i; - for (i = 0; i < SS7FirewallConfig.lua_blacklist_rules.size(); i++) { - try { - eng.eval("y = " + (String)SS7FirewallConfig.lua_blacklist_rules.get(i)); - boolean r = Boolean.valueOf(eng.get("y").toString()); - lua_match |= r; - if (r) { - //logger.debug("============ LUA rules blacklist: " + SS7FirewallConfig.lua_blacklist_rules.get(i) + " ============"); - //logger.debug("============ LUA variables ============"); - //for (String key : lua_hmap.keySet()) { - // logger.debug(key + ": " + lua_hmap.get(key)); - //} - break; + // -------------- Externel Firewall rules ----------------- + if (externalFirewallRules.ss7FirewallRules(message) == false) { + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "SS7 FW: Match with Externel Firewall rules", lua_hmap); + return; } - } catch (ScriptException ex) { - java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - } - } - if (lua_match) { - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Match with Lua rule " + i, lua_hmap); - return; - } - // ------------------------------------------ - - // ------------- IDS API rules --------------- - if (connectorIDS != null) { - EncodingResultData erd; - try { - erd = ((SccpMessageImpl)message).encode(this.sccpStack, lmrt, mup.getMaxUserDataLength(dpc), logger, this.sccpStack.isRemoveSpc(), - this.sccpStack.getSccpProtocolVersion()); - if(connectorIDS.evalSCCPMessage(DatatypeConverter.printHexBinary(erd.getSolidData())) == false) { - firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Blocked by IDS", lua_hmap); + + // -------------- LUA rules ----------------- + ScriptEngineManager mgr = new ScriptEngineManager(); + ScriptEngine eng = mgr.getEngineByName("luaj"); + for (String key : lua_hmap.keySet()) { + eng.put(key, lua_hmap.get(key)); + } + + boolean lua_match = false; + int i; + for (i = 0; i < SS7FirewallConfig.lua_blacklist_rules.size(); i++) { + try { + eng.eval("y = " + (String)SS7FirewallConfig.lua_blacklist_rules.get(i)); + boolean r = Boolean.valueOf(eng.get("y").toString()); + lua_match |= r; + if (r) { + //logger.debug("============ LUA rules blacklist: " + SS7FirewallConfig.lua_blacklist_rules.get(i) + " ============"); + //logger.debug("============ LUA variables ============"); + //for (String key : lua_hmap.keySet()) { + // logger.debug(key + ": " + lua_hmap.get(key)); + //} + break; + } + } catch (ScriptException ex) { + java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } + } + if (lua_match) { + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Match with Lua rule " + i, lua_hmap); return; } - } catch (ParseException ex) { - java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - } - } - // ------------------------------------------ - - // --------------- TCAP signing --------------- - if (tag == TCBeginMessage._TAG) { - KeyPair keyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.calling_gt_signing, message.getCallingPartyAddress().getGlobalTitle().getDigits()); - if (keyPair != null) { - lmrt = crypto.tcapSign(message, tcb, comps, lmrt, keyPair); - } - } - // -------------------------------------------- - - // ------------ TCAP encryption ------------- - if (message.getCalledPartyAddress() != null) { - if (message.getCalledPartyAddress().getGlobalTitle() != null) { - PublicKey publicKey = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.called_gt_encryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); - if (publicKey != null) { - Pair p = crypto.tcapEncrypt(message, sccpMessageFactory, publicKey, lmrt); - message = p.getKey(); - lmrt = p.getValue(); + // ------------------------------------------ + + // ------------- IDS API rules --------------- + if (connectorIDS != null) { + EncodingResultData erd; + try { + erd = ((SccpMessageImpl)message).encode(SS7Firewall.sccpStack, lmrt, mup.getMaxUserDataLength(dpc), logger, SS7Firewall.sccpStack.isRemoveSpc(), + SS7Firewall.sccpStack.getSccpProtocolVersion()); + if(connectorIDS.evalSCCPMessage(DatatypeConverter.printHexBinary(erd.getSolidData())) == false) { + firewallMessage(mup, mupReturn, opc, dpc, sls, ni, lmrt, message, "MAP FW: Blocked by IDS", lua_hmap); + return; + } + } catch (ParseException ex) { + java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } } - // ------------ Encryption Autodiscovery ------------ - // only if not towards HPLMN - else if (SS7FirewallConfig.encryption_autodiscovery.equals("true") - && tag == TCBeginMessage._TAG - && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) - && SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - - if (!encryption_autodiscovery_sessions.containsKey(message.getCalledPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length())))) { - logger.debug("============ Preparing Autodiscovery Invoke ============ "); + // ------------------------------------------ - TCBeginMessage t = TcapFactory.createTCBeginMessage(); + // --------------- TCAP signing --------------- + if (tag == TCBeginMessage._TAG) { + KeyPair keyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.calling_gt_signing, message.getCallingPartyAddress().getGlobalTitle().getDigits()); + if (keyPair != null) { + lmrt = crypto.tcapSign(message, tcb, comps, lmrt, keyPair); + } + } + // -------------------------------------------- + // ------------ TCAP encryption ------------- + if (message.getCalledPartyAddress() != null) { + if (message.getCalledPartyAddress().getGlobalTitle() != null) { + PublicKey publicKey = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.called_gt_encryption, message.getCalledPartyAddress().getGlobalTitle().getDigits()); + if (publicKey != null) { + Pair p = crypto.tcapEncrypt(message, sccpMessageFactory, publicKey, lmrt); + message = p.getKey(); + lmrt = p.getValue(); + } + // ------------ Encryption Autodiscovery ------------ + // only if not towards HPLMN + else if (SS7FirewallConfig.encryption_autodiscovery.equals("true") + && tag == TCBeginMessage._TAG + && !SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCalledPartyAddress().getGlobalTitle().getDigits()) + && SS7FirewallConfig.simpleWildcardCheck(SS7FirewallConfig.hplmn_gt, message.getCallingPartyAddress().getGlobalTitle().getDigits())) { - byte[] otid = { (byte)randomGenerator.nextInt(256), (byte)randomGenerator.nextInt(256), (byte)randomGenerator.nextInt(256), (byte)randomGenerator.nextInt(256) }; - t.setOriginatingTransactionId(otid); - // Create Dialog Portion - DialogPortion dp = TcapFactory.createDialogPortion(); + if (!encryption_autodiscovery_sessions.containsKey(message.getCalledPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length())))) { + logger.debug("============ Preparing Autodiscovery Invoke ============ "); - dp.setOid(true); - dp.setOidValue(new long[] { 0, 0, 17, 773, 1, 1, 1 }); + TCBeginMessage t = TcapFactory.createTCBeginMessage(); - dp.setAsn(true); - DialogRequestAPDUImpl diRequestAPDUImpl = new DialogRequestAPDUImpl(); + byte[] otid = { (byte)randomGenerator.nextInt(256), (byte)randomGenerator.nextInt(256), (byte)randomGenerator.nextInt(256), (byte)randomGenerator.nextInt(256) }; - // TODO change Application Context - ApplicationContextNameImpl acn = new ApplicationContextNameImpl(); - acn.setOid(new long[] { 0, 4, 0, 0, 1, 0, 19, 2 }); + // to this as soon as possible to prevent concurrent threads to duplicate the autodiscovery + encryption_autodiscovery_sessions.put(message.getCalledPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length())), Utils.decodeTransactionId(otid)); - diRequestAPDUImpl.setApplicationContextName(acn); - diRequestAPDUImpl.setDoNotSendProtocolVersion(true); + t.setOriginatingTransactionId(otid); + // Create Dialog Portion + DialogPortion dp = TcapFactory.createDialogPortion(); - dp.setDialogAPDU(diRequestAPDUImpl); + dp.setOid(true); + dp.setOidValue(new long[] { 0, 0, 17, 773, 1, 1, 1 }); - t.setDialogPortion(dp); + dp.setAsn(true); - Component[] c = new Component[1]; + DialogRequestAPDUImpl diRequestAPDUImpl = new DialogRequestAPDUImpl(); - c[0] = new InvokeImpl(); - ((InvokeImpl)c[0]).setInvokeId(1l); - OperationCode oc = TcapFactory.createOperationCode(); - oc.setLocalOperationCode(OC_AUTO_ENCRYPTION); - ((InvokeImpl)c[0]).setOperationCode(oc); + // TODO change Application Context + ApplicationContextNameImpl acn = new ApplicationContextNameImpl(); + acn.setOid(new long[] { 0, 4, 0, 0, 1, 0, 19, 2 }); + diRequestAPDUImpl.setApplicationContextName(acn); + diRequestAPDUImpl.setDoNotSendProtocolVersion(true); - t.setComponent(c); - AsnOutputStream aos = new AsnOutputStream(); - try { - t.encode(aos); - } catch (EncodeException ex) { - java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); - } + dp.setDialogAPDU(diRequestAPDUImpl); - byte[] _d = aos.toByteArray(); - - LongMessageRuleType l = lmrt; - SccpDataMessage m = this.sccpMessageFactory.createDataMessageClass0(message.getCalledPartyAddress(), message.getCallingPartyAddress(), message.getData(), message.getOriginLocalSsn(), false, null, null); - m.setData(_d); + t.setDialogPortion(dp); + + Component[] c = new Component[1]; + + c[0] = new InvokeImpl(); + ((InvokeImpl)c[0]).setInvokeId(1l); + OperationCode oc = TcapFactory.createOperationCode(); + oc.setLocalOperationCode(OC_AUTO_ENCRYPTION); + ((InvokeImpl)c[0]).setOperationCode(oc); - // --------- Add also TCAP signature ------------ - KeyPair keyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.calling_gt_signing, message.getCallingPartyAddress().getGlobalTitle().getDigits()); - if (keyPair != null) { - lmrt = crypto.tcapSign(m, t, c, lmrt, keyPair); - } - // ---------------------------------------------- - - logger.info("============ Sending Autodiscovery Invoke ============ "); - - // Use XUDT if required - if (m.getData().length >= 240) { - l = LongMessageRuleType.XUDT_ENABLED; - } - sendSccpMessage(mup, opc, dpc, sls, ni, l, m); - encryption_autodiscovery_sessions.put(message.getCalledPartyAddress().getGlobalTitle().getDigits().substring(0, Math.min(encryption_autodiscovery_digits, message.getCallingPartyAddress().getGlobalTitle().getDigits().length())), Utils.decodeTransactionId(otid)); + t.setComponent(c); + AsnOutputStream aos = new AsnOutputStream(); + try { + t.encode(aos); + } catch (EncodeException ex) { + java.util.logging.Logger.getLogger(SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } + + byte[] _d = aos.toByteArray(); + + LongMessageRuleType l = lmrt; + SccpDataMessage m = SS7Firewall.sccpMessageFactory.createDataMessageClass0(message.getCalledPartyAddress(), message.getCallingPartyAddress(), message.getData(), message.getOriginLocalSsn(), false, null, null); + m.setData(_d); + + // --------- Add also TCAP signature ------------ + KeyPair keyPair = SS7FirewallConfig.simpleWildcardFind(SS7FirewallConfig.calling_gt_signing, message.getCallingPartyAddress().getGlobalTitle().getDigits()); + if (keyPair != null) { + lmrt = crypto.tcapSign(m, t, c, lmrt, keyPair); + } + // ---------------------------------------------- + + logger.info("============ Sending Autodiscovery Invoke ============ "); + + // Use XUDT if required + if (m.getData().length >= 240) { + l = LongMessageRuleType.XUDT_ENABLED; + } + sendSccpMessage(mup, opc, dpc, sls, ni, l, m); + + } + // ---------- Encryption Autodiscovery End ---------- + } } - // ---------- Encryption Autodiscovery End ---------- } + // ------------------------------------------ + + logger.debug("============ Forwarding Message ============ "); + // Use XUDT if required + if (message.getData().length >= 240) { + lmrt = LongMessageRuleType.XUDT_ENABLED; + SccpDataMessage m = SS7Firewall.sccpMessageFactory.createDataMessageClass0(message.getCalledPartyAddress(), message.getCallingPartyAddress(), message.getData(), message.getOriginLocalSsn(), false, null, null); + message = m; + } + sendSccpMessage(mup, opc, dpc, sls, ni, lmrt, message); } - } - // ------------------------------------------ - - logger.debug("============ Forwarding Message ============ "); - // Use XUDT if required - if (message.getData().length >= 240) { - lmrt = LongMessageRuleType.XUDT_ENABLED; - SccpDataMessage m = this.sccpMessageFactory.createDataMessageClass0(message.getCalledPartyAddress(), message.getCallingPartyAddress(), message.getData(), message.getOriginLocalSsn(), false, null, null); - message = m; - } - sendSccpMessage(mup, opc, dpc, sls, ni, lmrt, message); - + }); } /** diff --git a/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7FirewallPerformanceTests.java b/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7FirewallPerformanceTests.java index 2640c9d..f2ab91d 100644 --- a/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7FirewallPerformanceTests.java +++ b/sigfw/sigfw.sigfw/src/main/java/ss7fw/SS7FirewallPerformanceTests.java @@ -34,6 +34,7 @@ import java.util.Map; import java.util.Properties; import java.util.logging.Level; +import javax.xml.bind.DatatypeConverter; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.mobicents.protocols.api.Association; @@ -60,6 +61,7 @@ public class SS7FirewallPerformanceTests implements ManagementEventListener, Ass private boolean sctpServerAssociationUp = false; NettyAssociationImpl clientAssociation = null; int messagesRecieved = 0; + int errorMessagesRecieved = 0; // IN, OUT MAX SCTP STREAMS private static Map sctpAssciationsMaxInboundStreams = new HashMap(); @@ -222,13 +224,13 @@ private void start() { long startTime = System.nanoTime(); - int max_messages = 20000; + int max_messages = 500000; for (int i = 0; i < max_messages; i++) { // processUnstructuredSS-Request streamNumber = i; - bytes = hexStringToByteArray("01000101000000b80006000800000064021000a50000000100000002030200010901030e190b12080012042222222222220b12080012041111111111117762754804000000016b432841060700118605010101a036603480020780a109060704000001001302be232821060704000001010101a016a01480099611111111111111f18107961111111111f16c28a12602010002013b301e04010f0410aa582ca65ac562b1582c168bc562b1118007911111111111f1000000"); + bytes = hexStringToByteArray("01000101000000b80006000800000064021000a50000000100000002030200010901030e190b12080012040000000000000b12080012041111111111117762754804000000016b432841060700118605010101a036603480020780a109060704000001001302be232821060704000001010101a016a01480099611111111111111f18107961111111111f16c28a12602010002013b301e04010f0410aa582ca65ac562b1582c168bc562b1118007911111111111f1000000"); byteBuffer = ByteBuffer.wrap(bytes); if (sctpAssciationsMaxInboundStreams.containsKey(a)) { sn = streamNumber % sctpAssciationsMaxInboundStreams.get(a).intValue(); @@ -239,12 +241,13 @@ private void start() { if (i%100 == 0) { log.info("Messages sent ........ #" + i); log.info("Messages recieved ........ #" + messagesRecieved); + log.info("Error Messages recieved .. #" + errorMessagesRecieved); } // if there is more than 2000 messages sent and not recieved // throttle sending to not overflow the recieving buffer - if (i - messagesRecieved > 2000) { - Thread.currentThread().sleep(100); + if (i - messagesRecieved > 5000) { + Thread.currentThread().sleep(10); } } @@ -256,6 +259,7 @@ private void start() { log.info("Messages sent ........ #" + max_messages); log.info("Messages recieved ........ #" + messagesRecieved); + log.info("Error Messages recieved .. #" + errorMessagesRecieved); } long estimatedTime = System.nanoTime() - startTime; @@ -422,7 +426,14 @@ public void onCommunicationRestart(Association asctn) { public void onPayload(Association asctn, PayloadData pd) { log.debug("[[[[[[[[[[ onPayload ]]]]]]]]]]"); - if (messagesRecieved == 0) { + ByteBuffer buf = ByteBuffer.wrap(pd.getData()); + byte[] arr = new byte[buf.remaining()]; + buf.get(arr); + + // ASPUP recieved + if (DatatypeConverter.printHexBinary(arr).equals("01000301000000100011000800000003".toUpperCase())) { + + log.info("[[[[[[[[[[ ASPUP recieved ]]]]]]]]]]"); // Answer try { @@ -439,13 +450,18 @@ public void onPayload(Association asctn, PayloadData pd) { sn = streamNumber % sctpAssciationsMaxInboundStreams.get(asctn.getName()).intValue(); } payloadData = new PayloadData(byteBuffer.array().length, byteBuffer.array(), true, false, 3, sn); - asctn.send(payloadData); + asctn.send(payloadData); + + log.info("[[[[[[[[[[ ASPUP_ACK sent ]]]]]]]]]]"); + } catch (Exception ex) { java.util.logging.Logger.getLogger(SS7FirewallPerformanceTests.class.getName()).log(Level.SEVERE, null, ex); } } - - if (messagesRecieved == 1) { + // ASPAC recieved + else if (DatatypeConverter.printHexBinary(arr).equals("0100040100000018000b0008000000020006000800000064".toUpperCase())) { + + log.info("[[[[[[[[[[ ASPAC recieved ]]]]]]]]]]"); // Answer try { @@ -464,6 +480,8 @@ public void onPayload(Association asctn, PayloadData pd) { payloadData = new PayloadData(byteBuffer.array().length, byteBuffer.array(), true, false, 3, sn); asctn.send(payloadData); + log.info("[[[[[[[[[[ ASPAC_ACK sent ]]]]]]]]]]"); + Thread.currentThread().sleep(1000); // NTFY @@ -475,12 +493,53 @@ public void onPayload(Association asctn, PayloadData pd) { payloadData = new PayloadData(byteBuffer.array().length, byteBuffer.array(), true, false, 3, sn); asctn.send(payloadData); + log.info("[[[[[[[[[[ NTFY sent ]]]]]]]]]]"); + } catch (Exception ex) { java.util.logging.Logger.getLogger(SS7FirewallPerformanceTests.class.getName()).log(Level.SEVERE, null, ex); } } - - messagesRecieved++; + // ASPUP_ACK recieved + else if (DatatypeConverter.printHexBinary(arr).equals("01000304000000100011000800000002".toUpperCase())) { + + log.info("[[[[[[[[[[ ASPUP_ACK recieved ]]]]]]]]]]"); + } + // ASPAC_ACK recieved + else if (DatatypeConverter.printHexBinary(arr).equals("0100040300000018000B0008000000020006000800000064".toUpperCase())) { + + log.info("[[[[[[[[[[ ASPAC_ACK recieved ]]]]]]]]]]"); + } + // NTFY recieved + else if (DatatypeConverter.printHexBinary(arr).equals("0100000100000020000d00080001000200110008000000020006000800000064".toUpperCase())) { + + log.info("[[[[[[[[[[ NTFY recieved ]]]]]]]]]]"); + } + // NTFY recieved + else if (DatatypeConverter.printHexBinary(arr).equals("0100000100000020000d00080001000300110008000000020006000800000064".toUpperCase())) { + + log.info("[[[[[[[[[[ NTFY recieved ]]]]]]]]]]"); + } + else { + + // OK - The same USSD as was sent was recieved + // 01000101000000B80006000800000064021000A50000000100000002030000010901030E190B12080012040000000000000B12080012041111111111117762754804000000016B432841060700118605010101A036603480020780A109060704000001001302BE232821060704000001010101A016A01480099611111111111111F18107961111111111F16C28A12602010002013B301E04010F0410AA582CA65AC562B1582C168BC562B1118007911111111111F1000000 + // 01000101000000B80006000800000064021000A50000000100000002030000010901030E190B12080012040000000000000B12080012041111111111117762754804000000016B432841060700118605010101A036603480020780A109060704000001001302BE232821060704000001010101A016A01480099611111111111111F18107961111111111F16C28A12602010002013B301E04010F0410AA582CA65AC562B1582C168BC562B1118007911111111111F1000000 + if (DatatypeConverter.printHexBinary(arr).equals("01000101000000B80006000800000064021000A50000000100000002030000010901030E190B12080012040000000000000B12080012041111111111117762754804000000016B432841060700118605010101A036603480020780A109060704000001001302BE232821060704000001010101A016A01480099611111111111111F18107961111111111F16C28A12602010002013B301E04010F0410AA582CA65AC562B1582C168BC562B1118007911111111111F1000000")) { + + } + // OK - The USSD just differently encoded after 2 FWs + // 01000101000000b80006000800000064021000a700000001000000020300000111000f040f1a000b12080012040000000000000b12080012041111111111117762754804000000016b432841060700118605010101a036603480020780a109060704000001001302be232821060704000001010101a016a01480099611111111111111f18107961111111111f16c28a12602010002013b301e04010f0410aa582ca65ac562b1582c168bc562b1118007911111111111f100 + else if (DatatypeConverter.printHexBinary(arr).equals("01000101000000b80006000800000064021000a700000001000000020300000111000f040f1a000b12080012040000000000000b12080012041111111111117762754804000000016b432841060700118605010101a036603480020780a109060704000001001302be232821060704000001010101a016a01480099611111111111111f18107961111111111f16c28a12602010002013b301e04010f0410aa582ca65ac562b1582c168bc562b1118007911111111111f100".toUpperCase())) { + + } + // report error + else { + log.warn(DatatypeConverter.printHexBinary(arr)); + errorMessagesRecieved++; + } + + messagesRecieved++; + } } @Override diff --git a/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_DiameterFirewall.java b/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_DiameterFirewall.java index ee83302..3ce01e1 100644 --- a/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_DiameterFirewall.java +++ b/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_DiameterFirewall.java @@ -115,6 +115,11 @@ public void testULR() { Logger.getLogger(Test_DiameterFirewall.class.getName()).log(Level.SEVERE, null, ex); } + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("This ULR message (CommandCode 316, Request) should be allowed by LUA rules diameter_orig_realm", !sigfw.unitTestingFlags_sendDiameterMessage); diff --git a/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_SS7Firewall.java b/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_SS7Firewall.java index bc399eb..3d567d5 100644 --- a/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_SS7Firewall.java +++ b/sigfw/sigfw.sigfw/src/test/java/sigfw/tests/Test_SS7Firewall.java @@ -25,6 +25,7 @@ package sigfw.tests; import java.util.logging.Level; +import java.util.logging.Logger; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -81,6 +82,12 @@ public void testATI() { sigfw.resetUnitTestingFlags(); SccpDataMessage sccpDataMessage = sigfw.sccpStack.getSccpProvider().getMessageFactory().createDataMessageClass0(calledParty, callingParty, hexStringToByteArray("627e4804000000026b432841060700118605010101a036603480020780a109060704000001001d03be232821060704000001010101a016a01480099611111111111111f18107961111111111f16c31a12f0201000201473027a009800711111111111111a10f80008100830084010086008500870083099611111111111111f1"), 0, true, null, null); sigfw.onMessage(sccpDataMessage); + + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("anyTimeInterrogation message (opCode 71, TCAP Begin) should be blocked by Cat1", !sigfw.unitTestingFlags_sendSccpMessage); } @@ -90,6 +97,12 @@ public void testPSL() { sigfw.resetUnitTestingFlags(); SccpDataMessage sccpDataMessage = sigfw.sccpStack.getSccpProvider().getMessageFactory().createDataMessageClass0(calledParty, callingParty, hexStringToByteArray("62454804000000536b1a2818060700118605010101a00d600ba1090607040000010026036c21a11f020101020153301730038001010407911111111111118307111111111111f1"), 0, true, null, null); sigfw.onMessage(sccpDataMessage); + + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("provideSubscriberLocation message (opCode 83, TCAP Begin) should be blocked by Cat1", !sigfw.unitTestingFlags_sendSccpMessage); } @@ -99,6 +112,12 @@ public void testSAI() { sigfw.resetUnitTestingFlags(); SccpDataMessage sccpDataMessage = sigfw.sccpStack.getSccpProvider().getMessageFactory().createDataMessageClass0(calledParty, callingParty, hexStringToByteArray("6516480433119839490402035ea26c08a106020102020138"), 0, true, null, null); sigfw.onMessage(sccpDataMessage); + + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("sendAuthenticationInfo message (opCode 56, TCAP Continue) should be allowed", sigfw.unitTestingFlags_sendSccpMessage); } @@ -108,6 +127,12 @@ public void testUSSD() { sigfw.resetUnitTestingFlags(); SccpDataMessage sccpDataMessage = sigfw.sccpStack.getSccpProvider().getMessageFactory().createDataMessageClass0(calledParty, callingParty, hexStringToByteArray("62754804000000016b432841060700118605010101a036603480020780a109060704000001001302be232821060704000001010101a016a01480099611111111111111f18107961111111111f16c28a12602010002013b301e04010f0410aa582ca65ac562b1582c168bc562b1118007911111111111f1"), 0, true, null, null); sigfw.onMessage(sccpDataMessage); + + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("processUnstructuredSSRequest message (opCode 59, TCAP Begin) should be allowed", sigfw.unitTestingFlags_sendSccpMessage); } @@ -117,6 +142,12 @@ public void testCL() { sigfw.resetUnitTestingFlags(); SccpDataMessage sccpDataMessage = sigfw.sccpStack.getSccpProvider().getMessageFactory().createDataMessageClass0(calledParty, callingParty, hexStringToByteArray("623b4804000000036b1a2818060700118605010101a00d600ba1090607040000010002036c17a115020101020103a30d040811111111111111f10a0100"), 0, true, null, null); sigfw.onMessage(sccpDataMessage); + + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("cancelLocation message (opCode 3, TCAP Begin) should be blocked by Cat2", !sigfw.unitTestingFlags_sendSccpMessage); } @@ -126,6 +157,12 @@ public void testPSI() { sigfw.resetUnitTestingFlags(); SccpDataMessage sccpDataMessage = sigfw.sccpStack.getSccpProvider().getMessageFactory().createDataMessageClass0(calledParty, callingParty, hexStringToByteArray("623e4804000000466b1a2818060700118605010101a00d600ba109060704000001001c036c1aa1180201010201463010800811111111111111f1a20480008300"), 0, true, null, null); sigfw.onMessage(sccpDataMessage); + + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("provideSubscriberInfo message (opCode 70, TCAP Begin) should be blocked by Cat2", !sigfw.unitTestingFlags_sendSccpMessage); } @@ -135,6 +172,12 @@ public void testPRN() { sigfw.resetUnitTestingFlags(); SccpDataMessage sccpDataMessage = sigfw.sccpStack.getSccpProvider().getMessageFactory().createDataMessageClass0(calledParty, callingParty, hexStringToByteArray("625d4804000000046b1a2818060700118605010101a00d600ba1090607040000010003026c39a137020101020104302f800811111111111111f18107111111111111f18207111111111111f1a5080a010104030401a0880791111111111111"), 0, true, null, null); sigfw.onMessage(sccpDataMessage); + + try { + Thread.currentThread().sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(Test_SS7Firewall.class.getName()).log(Level.SEVERE, null, ex); + } Assert.assertTrue("provideRoamingNumber message (opCode 4, TCAP Begin) should be blocked by Cat2", !sigfw.unitTestingFlags_sendSccpMessage); }