【发布时间】:2016-03-15 02:20:59
【问题描述】:
我正在尝试做的事情: 在设备上安装的两个应用程序之间实现轻量级、安全 IPC 协议。客户端应用应该能够向在服务应用中运行的Service 发送命令和查询,并接收返回的计算结果。
应用关系:两个应用的源代码都在我的控制之下,但应用会有不同的签名(不可协商)。
安全要求:服务应用应向单个客户端提供其服务。客户端的应用程序 ID(包名称)是已知的且不变的。
我尝试了什么:我尝试使用双向Messenger 通信方案(类似于this blog post)实现IPC。这种方法效果很好,但是我遇到了一个大问题——找不到客户端的UID,因此无法满足安全要求。
考虑在服务应用程序的Service 中找到的这段代码:
// 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;
}
}
});
这里的想法是,当客户端应用程序向此Service 发送消息时,它会将其本地“回调”Messenger 放入发送的Message 的replyTo 成员中。 Messenger 的文档指出:
注意:下面的实现只是一个简单的包装器 用于执行通信的 Binder。
所以我想我可以以某种方式将Messenger#getBinder() 返回的Binder 映射到客户的UID,但我现在遇到了麻烦:
-
Messenger#getBinder()返回 IBinder 不能转换为Binder - 即使我设法获得了对客户
Binder的引用,Binder#getCallingUid()方法也是static并且不接受参数...
所以,为了使这个特定的实现安全地工作,我需要找到一种方法来根据Message 的内容或基于客户端创建的特定Messenger 获取调用者的UID。由于 Android 的安全架构是围绕 Binders 构建的,因此没有直接的方法将 Binders 映射到 UIDs(或包名称)似乎很奇怪......那么,我该怎么做呢?
额外问题:除了 AIDL,Android 上是否还有其他 IPC 技术可以满足上述要求?
【问题讨论】:
-
当你从
handleMessage()内部调用静态getCallingUid()时,返回什么值?引用the documentation,getCallingUid()“返回分配给向您发送正在处理的当前事务的进程的Linux uid......如果当前线程当前没有执行传入事务,则返回它自己的uid”。在这种情况下,我怀疑你会得到自己的 UID,因为Handler,但至少值得一试。 -
"Android 上是否还有其他 IPC 技术可以满足上述要求?" -- 查看
getCallingUid()从服务的onStartCommand()返回什么,由客户端上的startService()触发。查看getCallingUid()从onReceive()或BroadcastReceiver返回的内容,用于客户端发送的广播。对于客户端通过ContentResolver发送的请求,查看getCallingUid()在ContentProvider(例如call())的方法中返回的内容。就个人而言,我只使用了基于 AIDL 的.Stub中的getCallingUid(),但我认为上述 1+ 应该可以工作。 -
@CommonsWare,确实,从
handleMessage()内部调用getCallingUid()返回服务的“自己的”UID。明天我会测试你建议的其他方法并提供反馈。 -
@CommonsWare,我尝试在所有
Service生命周期回调(onCreate()、onStartCommand()、onBind())中测试getCallingUid()——它们都返回了“自己的”UID。也许您建议的其他方法之一会起作用,但是,即使是这种情况,它们也会使事情变得不直观,并可能造成潜在的性能瓶颈(只是我的猜测)。所以,我想,我最好开始编写 AIDL 合约...... -
您是否考虑过使用 Binder 作为服务器向客户端发出的令牌,然后将其作为每个后续客户端请求的一部分? Binder 在所有进程中都是唯一的,因此可以(并且正在)用作与包名称/签名相结合的安全身份。
标签: android ipc android-security android-binder