3

What I'm trying to do: implement lightweight, secure IPC protocol between two applications installed on the device. Client app should be able to send commands and queries to Service running in a service app, and receive back results of computations.

Apps relationship: source code of both apps is under my control, but the apps will have different signatures (non-negotiable).

Security requirements: service app should provide its services to a single client. Client's application ID (package name) is known and constant.

What I tried: I tried to implement IPC with two-way Messenger communication scheme (similar to this blog post). This approach works fine, but I encountered one major issue - I can't find a way to obtain UID of the client, therefore I can't satisfy security requirements.

Consider this code found in Service of the service application:

// This messenger will be used by the clients of this service in order to send commands
private Messenger inboxMessenger = new Messenger(new Handler() {

    @Override
    public void handleMessage(Message msg)

        // TODO: verify the identity of the client

        switch (msg.what) {
            case MSG_GET_DATA:
                returnDataToClient(msg.replyTo);
                break;
        }
    }
});

The idea here is that when the client app sends a message to this Service, it puts its local "callback" Messenger into replyTo member of the sent Message. Documentation for Messenger states that:

Note: the implementation underneath is just a simple wrapper around a Binder that is used to perform the communication.

so I thought that I could somehow map the Binder returned by Messenger#getBinder() to client's UID, but I'm now having troubles:

  1. Messenger#getBinder() returns IBinder which can't be cast to Binder
  2. Even if I do manage to get a reference to client's Binder, the method Binder#getCallingUid() is static and does not accept arguments...

So, in order to make this particular implementation work securely, I need to find a way to obtain caller's UID based on the contents of Message or based on a particular Messenger which was created by the client. Since Android's security architecture is built around Binders, it seems strange that there is no straightforward approach to mapping Binders to UIDs (or package names)... So, how can I do this?

Bonus question: except for AIDL, is there any other IPC technique on Android that fulfills the requirements stated above?

Onik
  • 19,396
  • 14
  • 68
  • 91
Vasiliy
  • 16,221
  • 11
  • 71
  • 127
  • When you call the static `getCallingUid()` from inside `handleMessage()`, what value is returned? Quoting [the documentation](http://developer.android.com/reference/android/os/Binder.html#getCallingUid%28%29), `getCallingUid()` "Return the Linux uid assigned to the process that sent you the current transaction that is being processed... If the current thread is not currently executing an incoming transaction, then its own uid is returned". In this case, I suspect that you'll get your own UID, due to the `Handler`, but it's at least worth a shot. – CommonsWare Dec 09 '15 at 17:34
  • "is there any other IPC technique on Android that fulfills the requirements stated above?" -- see what `getCallingUid()` returns from `onStartCommand()` of the service, triggered by `startService()` on the client. See what `getCallingUid()` returns from `onReceive()` of a `BroadcastReceiver`, for a broadcast sent by the client. See what `getCallingUid()` returns in methods of `ContentProvider` (e.g., `call()`), for requests sent by the client via a `ContentResolver`. Personally, I have only used `getCallingUid()` from an AIDL-based `.Stub`, but I would think that 1+ of the above should work. – CommonsWare Dec 09 '15 at 17:37
  • @CommonsWare, indeed, call to `getCallingUid()` from inside `handleMessage()` return service's "own" `UID`. I'll test the other approaches you suggested tomorrow and provide a feedback. – Vasiliy Dec 09 '15 at 18:08
  • @CommonsWare, I tried to test `getCallingUid()` in all `Service` lifecycle callbacks (`onCreate()`, `onStartCommand()`, `onBind()`) - all of them returned "own" `UID`. Maybe one of the other approaches you suggested would work, but, even if this is the case, they will make things non-intuitive and might create potential performance bottlenecks (just a speculation of mine). So, I guess, I'd better start coding AIDL contract... – Vasiliy Dec 10 '15 at 07:52
  • Have you considered using a Binder as a token issued to the client by the server, and then required as part of every subsequent client request? Binders are unique among all process and thus can be (and are) used as a secure identity combined with package name/signature. – Paul Ratazzi Dec 22 '15 at 20:55
  • @PaulRatazzi, the service will need to have some means by which it "authorizes" the clients before it issues `Binder` tokens - this authorization mechanism is exactly what I can't find a way to implement using `Messenger` based IPC... Any ideas as to how to do this? – Vasiliy Dec 22 '15 at 22:12

2 Answers2

3

After some research and experimentation, I came to conclusion that Android does not provide an alternative to AIDL when it comes to secured, signature protected communication.

The good news are that AIDL is not difficult to implement and official tutorials on this particular subject are not bad at all.

Vasiliy
  • 16,221
  • 11
  • 71
  • 127
-1

You can check the client's signature in server side, to make sure it's qualified.

Swing
  • 858
  • 1
  • 8
  • 21
  • I was looking for a way to obtain the signature - if I could have it, then I wouldn't ask the question. – Vasiliy Jan 12 '16 at 08:36
  • You have google! http://stackoverflow.com/questions/5578871/how-to-get-app-signature/5579239#5579239 – Swing Jan 13 '16 at 08:03