Identify Calling Application in Android NDK - android

I have a native android library (.so) I am bundling with some application. In the native code I want to verify the signer/package name of the calling application.
The reason is, currently anyone can open up the .apk file take my .so file and use it to built their own applications.
Is there a way to securely identify the calling application from Java side? This could be package name, signature or anything else that can identify the Android application in a unique way.

JNI code is coupled with Java package name, and can be called only from the same package and class. To improve security further, you can check some Java private static final field from the JNI code.

In the native code I want to verify the signer/package name of the
calling application.
how about this?
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_x_y_TestActivity_stringFromJNI(JNIEnv *env, jobject thiz)
{
jclass jActivity_class = env->GetObjectClass(thiz);
jmethodID jMethod_id_pn = env->GetMethodID(jActivity_class,"getPackageName","()Ljava/lang/String;");
jstring package_name = (jstring) env->CallObjectMethod(thiz,jMethod_id_pn);
return package_name;
}

Related

C++ on android, how to get app's document directory?

I'm integrating a native c++ library (sqlite3) into android, in order to save the database file I need a path to put it somewhere, on iOS I used this code to get the documents directory:
char *home = getenv("HOME");
However this environment variable not available on Android, is there anyway to get the applications documents path from the c++ or is it necessary to always get it from some higher java call?
Thanks a lot for the help!
Edit
After looking around, I found this small snippet that I already had in my codebase:
SequelModule.initialize(
this.getReactApplicationContext().getJavaScriptContextHolder().get(),
this.getReactApplicationContext().getFilesDir().getAbsolutePath()
);
which is being passed to my cpp-adapter.cpp, how do I convert the second value (the absolute path) JNI/Java string into a C++ std::string?
#include <jni.h>
#include "react-native-sequel.h"
extern "C"
JNIEXPORT void JNICALL
Java_com_reactnativesequel_SequelModule_initialize(JNIEnv* env, jclass clazz, jlong jsiPtr) {
installSequel(*reinterpret_cast<facebook::jsi::Runtime*>(jsiPtr));
}
extern "C"
JNIEXPORT void JNICALL
Java_com_reactnativesequel_SequelModule_destruct(JNIEnv* env, jclass clazz) {
cleanUpSequel();
}

undefined lame decode function

I'm trying to add MP3 read and write capabilities to my Android app. I'm using the lame4android app as a starting point. Encoding a file works for me, but I'm having a problem with the decode functions -- I'm getting undefined references to the decode functions.
Here are excerpts from my wrapper.c:
#include "libmp3lame/lame.h"
#include "jni.h"
lame_t lame;
jint Java_com_intonia_dandy_WavStream_initEncoder(JNIEnv *env,
jobject jobj,
jint in_num_channels,
jint in_samplerate)
{
lame = lame_init();
...
return lame_init_params(lame);
}
hip_t hip;
jint Java_com_intonia_dandy_WavStream_initDecoder(JNIEnv *env, jobject jobj)
{
hip = hip_decode_init();
return hip != 0;
}
And here are the declarations from lame.h:
lame_global_flags * CDECL lame_init(void);
typedef hip_global_flags *hip_t;
hip_t CDECL hip_decode_init(void);
I'm getting an error message:
C:/ACode/dandy/src/main/jni/./wrapper.c:62: undefined reference to `hip_decode_init`
I'm also getting undefined references to hip_decode and and hip_decode_exit. But lame_init, lame_init_params, lame_encode_buffer, and lame_encode_flush do not generate any errors. I get these errors using the command line to run ndk-build, and I get the same errors when I let Android Studio manage the compilation.
How are the lame_* functions different from the hip_decode_* functions? Should I be using the deprecated lame_decode_*?
EDIT: I'm looking at the output of the ndk-build command. The .c files are listed on the console as they are compiled. hip_decode_init is defined in jni/libmp3lame/mpglib_interface.c, but mpglib_interface is not getting compiled, even though it's listed in jni/Android.mk. Why not???
It turns out that the LAME library as distributed does not have decoding enabled. To get it working, I had to do the following:
Add #define HAVE_MPGLIB 1 to mpglib_interface.c
Copy all .c and .h files from the mpglib directory of the LAME distribution.
Edit Android.mk to include the .c files from mpglib.
EDIT: instead of modifying mpglib_interface.c to define HAVE_MPGLIB,
it's better to set compilation flags.
Working with Android Studio 2+, build.gradle should contain
android {
defaultConfig {
ndk {
moduleName "libmp3lame"
cFlags "-DSTDC_HEADERS -DHAVE_MPGLIB"
}
}
}
Or in Android.mk:
LOCAL_CFLAGS = -DSTDC_HEADERS -DHAVE_MPGLIB

Unresolved symbols NewShortArray and SetShortArrayRegion

I'm trying to use short[] and jshortArray between C/JAVA as follows in Eclipse:
JNIEXPORT void JNICALL Java_com_testingForFun_testFunc
(JNIEnv *env, jclass clazz, jshort num, jshortArray data) {
jshort outCArray[] = {100, 200};
jshortArray outJNIArray = (*env)->NewShortArray(env, 2); // allocate
if (NULL == outJNIArray) return;
(*env)->SetShortArrayRegion(env, outJNIArray, 0 , 2, outCArray); // copy
//return outJNIArray;
}
I've created the header file using javah and included it. However, Eclipse says NewShortArray and SetShortArrayRegion are unresolved and I can't build the apk. However, not using arrays (jshort and short) works fine. I looked in jni.h and it seems that NewShortArray other related functions are defined if __cplusplus is defined, but I'm using C. I also built the apk on the command line using ndk-build and ant and I read outJNIArray[0] or [1] = 0 in the calling function, so it's not working there either. How do I resolve this issue?
Additionally, Eclipse can't resolve ANDROID_LOG_DEBUG in:
__android_log_print(ANDROID_LOG_DEBUG, "FibLib.c", "fibNI(%lld)", n);
even though
#include <android/log.h>
is at the beginning of the file.
I used Eclipse restart and seems to have cleared up these issues. But every time I edit my .c file, the unresolved errors pop up, and I need to restart. It's very annoying. Any fix for this?
The issue of outJNIArray[] not being set is a separate topic, so I will ask another question on the forum in the future if necessary.

NDK unable to deal with #include with relative paths?

I'm writing an Adroid app with some C++ code behind the UI using Eclipse + NDK (r8d). I have some code that I thought was fool proof but the compiler just gives me weird errors like "Invalid arguments" without specifics. Here is what my C++ code looks like:
#include <jni.h>
#include <string>
using namespace std;
#include "../../Evaluator.Engine/Evaluator.Engine.h"
Evaluator evaluator;
extern "C" {
JNIEXPORT jstring JNICALL Java_haskellevaluator_android_MainActivity_evaluateNative(JNIEnv *env, jobject, jstring jInput)
{
...
string sInput(L"Hello world");
string sResult = evaluator.evaluate(sInput);
jstring jResult = env->NewStringUTF(sResult.data());
return jResult;
}
}
Evaluator.Engine.h is nothing fancy, but just a declaration of the class Evaluator.
#include <string>
using namespace std;
class Evaluator
{
public:
string evaluate(string input);
};
However, the compiler complains:
Invalid arguments '
Candidates are:
? evaluate(?)
'
as if string is not defined. But if I put a copy of the header file under the same folder, the error goes away. This is a Windows box. I have tried using \ and escaped \\ as path separators and it didn't work.
Does this sound like a NDK (or whatever the preprocessor it uses) bug? I don't want to move the header file because it'll be shared by other projects. I also hate to keep 2 copies of the same file.
Any ideas? Thanks.
Sorry I don't have windows OS, but I've tried you code on a MacOS, but it doesn't work because of:
string sInput(L"Hello world");
Saying that wchar_t cannot be put on std::string. Is it possible to be the same problem ?

include .h file into java file in android using jni as source folder of .h file?

void ProcedureParams_Initialize(ProcedureParams* pVal);
flag ProcedureParams_IsConstraintValid(const ProcedureParams* val, int* pErrCode);
flag ProcedureParams_XER_Encode(const ProcedureParams* val, ByteStream* pByteStrm, int* pErrCode, flag bCheckConstraints);
flag ProcedureParams_XER_Decode(ProcedureParams* pVal, ByteStream* pByteStrm, int* pErrCode);
flag ProcedureParams_BER_Encode(const ProcedureParams* val, ByteStream* pByteStrm, int* pErrCode, flag bCheckConstraints);
flag ProcedureParams_BER_Decode(ProcedureParams* pVal, ByteStream* pByteStrm, int* pErrCode);
typedef struct {
GeneralEvthParams g_params;
DataParams d_params;
} EvtHandlerParams;
how i can add .h file directly into my .java file. i'm using NDk and .h file inside my jni folder.i want to use the functions of header file . how i can directly use functions in java activity? please help me
You cannot invoke the C/C++ functions directly. The C implementations of Java native functions all have a very specific set of parameters:
JNIEXPORT jint JNICALL Java_com_mycompany_MyClassName_myfunc
(JNIEnv * env, jobject obj, jint code) {
...
}
So you will have to create wrapper functions.
A reasonable approach is to define a class including the Java versions of all your native functions (as either static or instance methods), and invoke them via that class.
To generate C headers from the Java (well, not source but the .class files), you can do:
cd bin/classes
javah com.mycompany.MyClassName com.mycompany.AnotherClassName

Categories

Resources