@@ -5,22 +5,26 @@ import TalsecRuntime
55class FreeraspReactNative : RCTEventEmitter {
66
77 public static var shared : FreeraspReactNative ?
8+
9+ let threatChannelKey = String ( Int . random ( in: 100_000 ..< 999_999_999 ) ) // key of the argument map under which threats are expected
10+ let threatChannelName = String ( Int . random ( in: 100_000 ..< 999_999_999 ) ) // name of the channel over which threat callbacks are sent
11+ let threatIdentifierList = ( 1 ... 12 ) . map { _ in Int . random ( in: 100_000 ..< 999_999_999 ) }
812
913 override init ( ) {
1014 super. init ( )
1115 FreeraspReactNative . shared = self
1216 }
1317
14- @objc ( talsecStart: )
15- func talsecStart( options: NSDictionary ) -> Void {
18+ @objc ( talsecStart: withResolver : withRejecter : )
19+ func talsecStart( options: NSDictionary , resolve : RCTPromiseResolveBlock , rejecter reject : RCTPromiseRejectBlock ) -> Void {
1620 do {
1721 try initializeTalsec ( talsecConfig: options)
1822 }
1923 catch let error as NSError {
20- self . sendEvent ( withName : " initializationError " , body : error. localizedDescription )
24+ reject ( " initialization_error " , " Could not initialize freeRASP " , error)
2125 return
2226 }
23- self . sendEvent ( withName : " started " , body : " started " )
27+ resolve ( " freeRASP started" )
2428 }
2529
2630 func initializeTalsec( talsecConfig: NSDictionary ) throws {
@@ -41,25 +45,90 @@ class FreeraspReactNative: RCTEventEmitter {
4145 let config = TalsecConfig ( appBundleIds: [ appBundleIds] , appTeamId: appTeamId, watcherMailAddress: watcherMailAddress, isProd: isProd)
4246 Talsec . start ( config: config)
4347 }
48+
49+ /**
50+ * Method to setup the message passing between native and React Native
51+ */
52+ @objc ( getThreatChannelData: withRejecter: )
53+ private func getThreatChannelData( resolve: RCTPromiseResolveBlock , rejecter reject: RCTPromiseRejectBlock ) -> Void {
54+ resolve ( [ threatChannelName, threatChannelKey] )
55+ }
56+
57+ func dispatchEvent( securityThreat: SecurityThreat ) -> Void {
58+ FreeraspReactNative . shared!. sendEvent ( withName: threatChannelName, body: [ threatChannelKey: securityThreat. callbackIdentifier] )
59+ }
60+
61+ /**
62+ * Method to get the random identifiers of callbacks
63+ */
64+ @objc ( getThreatIdentifiers: withRejecter: )
65+ private func getThreatIdentifiers( resolve: RCTPromiseResolveBlock , rejecter reject: RCTPromiseRejectBlock ) -> Void {
66+ resolve ( getThreatIdentifiers ( ) )
67+ }
68+
69+ /**
70+ * We never send an invalid callback over our channel.
71+ * Therefore, if this happens, we want to kill the app.
72+ */
73+ @objc ( onInvalidCallback)
74+ private func onInvalidCallback( ) -> Void {
75+ abort ( )
76+ }
77+
78+ private func getThreatIdentifiers( ) -> [ Int ] {
79+ return SecurityThreat . allCases
80+ . filter {
81+ threat in threat. rawValue != " passcodeChange "
82+ }
83+ . map {
84+ threat in threat. callbackIdentifier
85+ }
86+ }
4487
4588 override func supportedEvents( ) -> [ String ] ! {
46- return [ " initializationError " , " started " , " privilegedAccess " , " debug " , " simulator " , " appIntegrity " , " unofficialStore " , " hooks " , " deviceBinding " , " deviceID " , " secureHardwareNotAvailable " , " passcodeChange " , " passcode " ]
89+ return [ threatChannelName ]
4790 }
4891}
4992
50- extension SecurityThreatCenter : SecurityThreatHandler {
93+ /// An extension to unify callback names with RN ones.
94+ extension SecurityThreat {
5195
96+ var callbackIdentifier : Int {
97+ switch self {
98+ case . signature:
99+ return FreeraspReactNative . shared!. threatIdentifierList [ 0 ]
100+ case . jailbreak:
101+ return FreeraspReactNative . shared!. threatIdentifierList [ 1 ]
102+ case . debugger:
103+ return FreeraspReactNative . shared!. threatIdentifierList [ 2 ]
104+ case . runtimeManipulation:
105+ return FreeraspReactNative . shared!. threatIdentifierList [ 3 ]
106+ case . passcode:
107+ return FreeraspReactNative . shared!. threatIdentifierList [ 4 ]
108+ case . passcodeChange:
109+ return FreeraspReactNative . shared!. threatIdentifierList [ 5 ]
110+ case . simulator:
111+ return FreeraspReactNative . shared!. threatIdentifierList [ 6 ]
112+ case . missingSecureEnclave:
113+ return FreeraspReactNative . shared!. threatIdentifierList [ 7 ]
114+ case . deviceChange:
115+ return FreeraspReactNative . shared!. threatIdentifierList [ 8 ]
116+ case . deviceID:
117+ return FreeraspReactNative . shared!. threatIdentifierList [ 9 ]
118+ case . unofficialStore:
119+ return FreeraspReactNative . shared!. threatIdentifierList [ 10 ]
120+ @unknown default :
121+ abort ( )
122+ }
123+ }
124+ }
52125
53- static let threatEventMap : [ String : String ] = [
54- " missingSecureEnclave " : " secureHardwareNotAvailable " ,
55- " device binding " : " deviceBinding " ,
56- ]
126+ extension SecurityThreatCenter : SecurityThreatHandler {
57127
58128 public func threatDetected( _ securityThreat: TalsecRuntime . SecurityThreat ) {
59- let threatName = SecurityThreatCenter . threatEventMap [ securityThreat. rawValue] ?? securityThreat. rawValue
60- if ( threatName == " passcodeChange " ) {
129+ if ( securityThreat. rawValue == " passcodeChange " ) {
61130 return
62131 }
63- FreeraspReactNative . shared!. sendEvent ( withName : threatName , body : threatName )
132+ FreeraspReactNative . shared!. dispatchEvent ( securityThreat : securityThreat )
64133 }
65134}
0 commit comments