Skip to content

Commit 44d8d0d

Browse files
authored
Merge pull request #35 from talsec/rename_callbacks
Rename callbacks
2 parents f4844e3 + 9d44bd3 commit 44d8d0d

File tree

11 files changed

+430
-148
lines changed

11 files changed

+430
-148
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# freeRASP 3.5.0
2+
3+
- ⚠️ Updated the `talsecStart()` method to return `Promise<string>`. If freeRASP starts successfuly, the method will return `freeRASP started` string. There are not any changes of the interface if you are using the provided `useFreeRasp` hook.
4+
- ⚡ Improved the message passing between native iOS/Android and React Native sides
5+
- ✔️ Restricted message passing to valid callbacks only. If an invalid callback is received, the SDK will kill the app
6+
17
# freeRASP 3.4.0
28

39
- 📄 Documentation updates and improvements

android/src/main/java/com/freeraspreactnative/FreeraspDeviceStateListener.kt

Lines changed: 0 additions & 25 deletions
This file was deleted.

android/src/main/java/com/freeraspreactnative/FreeraspReactNativeModule.kt

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,93 +4,85 @@ import com.aheaditec.talsec_security.security.api.Talsec
44
import com.aheaditec.talsec_security.security.api.TalsecConfig
55
import com.aheaditec.talsec_security.security.api.ThreatListener
66
import com.facebook.react.bridge.Arguments
7+
import com.facebook.react.bridge.Promise
78
import com.facebook.react.bridge.ReactApplicationContext
89
import com.facebook.react.bridge.ReactContextBaseJavaModule
910
import com.facebook.react.bridge.ReactMethod
10-
import com.facebook.react.bridge.WritableMap
1111
import com.facebook.react.bridge.ReadableMap
12+
import com.facebook.react.bridge.WritableArray
1213
import com.facebook.react.modules.core.DeviceEventManagerModule
1314

1415
class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
15-
ReactContextBaseJavaModule(reactContext), ThreatListener.ThreatDetected,
16-
FreeraspDeviceStateListener.DeviceStateListener {
16+
ReactContextBaseJavaModule(reactContext) {
1717

18-
private val listener = ThreatListener(this, FreeraspDeviceStateListener)
18+
private val listener = ThreatListener(FreeraspThreatHandler, FreeraspThreatHandler)
1919

2020
override fun getName(): String {
2121
return NAME
2222
}
2323

24+
init {
25+
appReactContext = reactContext
26+
}
27+
2428
@ReactMethod
2529
fun talsecStart(
26-
options: ReadableMap
30+
options: ReadableMap,
31+
promise: Promise
2732
) {
2833

2934
try {
3035
val config = parseTalsecConfig(options)
31-
FreeraspDeviceStateListener.listener = this
36+
FreeraspThreatHandler.listener = ThreatListener
3237
listener.registerListener(reactContext)
3338
Talsec.start(reactContext, config)
34-
sendOngoingPluginResult("started", null)
39+
promise.resolve("freeRASP started")
3540

3641
} catch (e: Exception) {
3742
val params = Arguments.createMap().apply {
3843
putString("message", e.message)
3944
}
40-
sendOngoingPluginResult("initializationError", params)
45+
promise.reject("initializationError", params)
4146
}
4247
}
4348

49+
/**
50+
* Method to get the random identifiers of callbacks
51+
*/
4452
@ReactMethod
45-
fun addListener(@Suppress("UNUSED_PARAMETER") eventName: String) {
46-
// Set up any upstream listeners or background tasks as necessary
53+
fun getThreatIdentifiers(promise: Promise) {
54+
promise.resolve(Threat.getThreatValues())
4755
}
4856

57+
/**
58+
* Method to setup the message passing between native and React Native
59+
* @return list of [THREAT_CHANNEL_NAME, THREAT_CHANNEL_KEY]
60+
*/
4961
@ReactMethod
50-
fun removeListeners(@Suppress("UNUSED_PARAMETER") count: Int) {
51-
// Remove upstream listeners, stop unnecessary background tasks
52-
}
53-
54-
override fun onRootDetected() {
55-
sendOngoingPluginResult("privilegedAccess", null)
56-
}
57-
58-
override fun onDebuggerDetected() {
59-
sendOngoingPluginResult("debug", null)
60-
}
61-
62-
override fun onEmulatorDetected() {
63-
sendOngoingPluginResult("simulator", null)
64-
}
65-
66-
override fun onTamperDetected() {
67-
sendOngoingPluginResult("appIntegrity", null)
68-
}
69-
70-
override fun onUntrustedInstallationSourceDetected() {
71-
sendOngoingPluginResult("unofficialStore", null)
62+
fun getThreatChannelData(promise: Promise) {
63+
val channelData: WritableArray = Arguments.createArray()
64+
channelData.pushString(THREAT_CHANNEL_NAME)
65+
channelData.pushString(THREAT_CHANNEL_KEY)
66+
promise.resolve(channelData)
7267
}
7368

74-
override fun onHookDetected() {
75-
sendOngoingPluginResult("hooks", null)
76-
}
77-
78-
override fun onDeviceBindingDetected() {
79-
sendOngoingPluginResult("deviceBinding", null)
80-
}
81-
82-
override fun onObfuscationIssuesDetected() {
83-
sendOngoingPluginResult("obfuscationIssues", null)
69+
/**
70+
* We never send an invalid callback over our channel.
71+
* Therefore, if this happens, we want to kill the app.
72+
*/
73+
@ReactMethod
74+
fun onInvalidCallback() {
75+
android.os.Process.killProcess(android.os.Process.myPid())
8476
}
8577

86-
override fun deviceStateChangeDetected(threatType: String) {
87-
sendOngoingPluginResult(threatType, null)
78+
@ReactMethod
79+
fun addListener(@Suppress("UNUSED_PARAMETER") eventName: String) {
80+
// Set up any upstream listeners or background tasks as necessary
8881
}
8982

90-
private fun sendOngoingPluginResult(eventName: String, params: WritableMap?) {
91-
reactContext
92-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
93-
.emit(eventName, params)
83+
@ReactMethod
84+
fun removeListeners(@Suppress("UNUSED_PARAMETER") count: Int) {
85+
// Remove upstream listeners, stop unnecessary background tasks
9486
}
9587

9688
private fun parseTalsecConfig(config: ReadableMap): TalsecConfig {
@@ -125,5 +117,23 @@ class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
125117

126118
companion object {
127119
const val NAME = "FreeraspReactNative"
120+
val THREAT_CHANNEL_NAME = (10000..999999999).random()
121+
.toString() // name of the channel over which threat callbacks are sent
122+
val THREAT_CHANNEL_KEY = (10000..999999999).random()
123+
.toString() // key of the argument map under which threats are expected
124+
private lateinit var appReactContext: ReactApplicationContext
125+
private fun notifyListeners(threat: Threat) {
126+
val params = Arguments.createMap()
127+
params.putInt(THREAT_CHANNEL_KEY, threat.value)
128+
appReactContext
129+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
130+
.emit(THREAT_CHANNEL_NAME, params)
131+
}
132+
}
133+
134+
internal object ThreatListener : FreeraspThreatHandler.TalsecReactNative {
135+
override fun threatDetected(threatType: Threat) {
136+
notifyListeners(threatType)
137+
}
128138
}
129139
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.freeraspreactnative
2+
3+
import com.aheaditec.talsec_security.security.api.ThreatListener
4+
5+
internal object FreeraspThreatHandler : ThreatListener.ThreatDetected, ThreatListener.DeviceState {
6+
7+
internal var listener: TalsecReactNative? = null
8+
9+
override fun onRootDetected() {
10+
listener?.threatDetected(Threat.PrivilegedAccess)
11+
}
12+
13+
override fun onDebuggerDetected() {
14+
listener?.threatDetected(Threat.Debug)
15+
}
16+
17+
override fun onEmulatorDetected() {
18+
listener?.threatDetected(Threat.Simulator)
19+
}
20+
21+
override fun onTamperDetected() {
22+
listener?.threatDetected(Threat.AppIntegrity)
23+
}
24+
25+
override fun onUntrustedInstallationSourceDetected() {
26+
listener?.threatDetected(Threat.UnofficialStore)
27+
}
28+
29+
override fun onHookDetected() {
30+
listener?.threatDetected(Threat.Hooks)
31+
}
32+
33+
override fun onDeviceBindingDetected() {
34+
listener?.threatDetected(Threat.DeviceBinding)
35+
}
36+
37+
override fun onObfuscationIssuesDetected() {
38+
listener?.threatDetected(Threat.ObfuscationIssues)
39+
}
40+
41+
override fun onUnlockedDeviceDetected() {
42+
listener?.threatDetected(Threat.Passcode)
43+
}
44+
45+
override fun onHardwareBackedKeystoreNotAvailableDetected() {
46+
listener?.threatDetected(Threat.SecureHardwareNotAvailable)
47+
}
48+
49+
internal interface TalsecReactNative {
50+
fun threatDetected(threatType: Threat)
51+
}
52+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.freeraspreactnative
2+
3+
import com.facebook.react.bridge.Arguments
4+
import com.facebook.react.bridge.WritableArray
5+
6+
/**
7+
* Sealed class to represent the error codes.
8+
*
9+
* Sealed classes are used because of obfuscation - enums classes are not obfuscated well enough.
10+
*
11+
* @property value integer value of the error code.
12+
*/
13+
internal sealed class Threat(val value: Int) {
14+
object AppIntegrity : Threat((10000..999999999).random())
15+
object PrivilegedAccess : Threat((10000..999999999).random())
16+
object Debug : Threat((10000..999999999).random())
17+
object Hooks : Threat((10000..999999999).random())
18+
object Passcode : Threat((10000..999999999).random())
19+
object Simulator : Threat((10000..999999999).random())
20+
object SecureHardwareNotAvailable : Threat((10000..999999999).random())
21+
object DeviceBinding : Threat((10000..999999999).random())
22+
object UnofficialStore : Threat((10000..999999999).random())
23+
object ObfuscationIssues : Threat((10000..999999999).random())
24+
25+
companion object {
26+
internal fun getThreatValues(): WritableArray {
27+
return Arguments.fromList(
28+
listOf(
29+
AppIntegrity.value,
30+
PrivilegedAccess.value,
31+
Debug.value,
32+
Hooks.value,
33+
Passcode.value,
34+
Simulator.value,
35+
SecureHardwareNotAvailable.value,
36+
DeviceBinding.value,
37+
UnofficialStore.value,
38+
ObfuscationIssues.value
39+
)
40+
)
41+
42+
}
43+
}
44+
}

ios/FreeraspReactNative.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@
44

55
@interface RCT_EXTERN_MODULE(FreeraspReactNative, RCTEventEmitter)
66

7-
RCT_EXTERN_METHOD(talsecStart:(NSDictionary*)options)
7+
RCT_EXTERN_METHOD(talsecStart:(NSDictionary*)options
8+
withResolver:(RCTPromiseResolveBlock)resolve
9+
withRejecter:(RCTPromiseRejectBlock)reject)
10+
RCT_EXTERN_METHOD(getThreatChannelData:(RCTPromiseResolveBlock)resolve
11+
withRejecter:(RCTPromiseRejectBlock)reject)
12+
RCT_EXTERN_METHOD(getThreatIdentifiers:(RCTPromiseResolveBlock)resolve
13+
withRejecter:(RCTPromiseRejectBlock)reject)
14+
RCT_EXTERN_METHOD(onInvalidCallback)
815

916
+ (BOOL)requiresMainQueueSetup
1017
{

0 commit comments

Comments
 (0)