2013-03-20 20 views
5

私は複数のアプリを制作する会社で働いていますが、すべてのアプリが同じ署名を持っているわけではありません。アンドロイド:インテント送信者の身元を確認する

同じデバイス上のすべてのコンパニエのアプリケーションが同じデバイスを共有するメカニズムを作成しようとしました たとえば、ユーザーがマーケットApp Aからインストールしてアプリをインストールしていない場合、新しいIDが生成されます彼はApp Aをインストールし、App BはApp Aと同じIDを持つべきです(IDは生成されたUUIDタイプ#4です)。

私たちは現時点では放送を使用しています。 idを別のブロードキャストでブロードキャストして返します(今回は明示的に指定します)。 ブロードキャストとレスポンスは、署名レベルで私たちの許可を得て保護されていますが、私たちは複数の署名を持っているので、もちろんこれは役に立ちません。

私はインテントブロードキャストを作成しようとしましたが、それは1つのシグネチャだけに限定されない独自の保護メカニズムを持つことができますが、Binder.getSenderUID()のようなものはブロードキャスト私は自分のuidを取得します。 それは、自分自身が自分のIDを意図して書くのでなければ、私は盗んだ人のアイデンティティを得る方法がないように見えますが、それは簡単に偽造できるので信頼できるものではありません。 暗号化を使用するには、アプリケーションに鍵が付いている必要があります。もう1度は保護されません。検証に時間がかかりすぎると、サーバーが有効になりすぎることがあります。

誰かがあるアプリから別のアプリへのvalidate \ secureメッセージをどのように得ることができるか考えています(私のすべてのアプリだが、署名が異なるかもしれない)。

答えて

2

遅くて申し訳ありません...

バインドには時間がかかりますが、より重要なのは非同期です。 しかし、同期バインドを作成する方法があります。当然、あなたが連絡しようとしているサービスはすでにその時点で開始されていると仮定します。 BroadcastReceiver(これは本質的に非同期なので、通常のbindServiceは使用できません)では、これ以上のAndroidの使用が許可されています.BroadcastReceiverには "peekService"メソッドがあります。

あなたは、あなたができることによって、放送を聞いてなくて、それを使用したい場合

:あなたがサービスにバインドするので、各使用上で覗き見することを確認していない

final IBinder[] b = new IBinder[1]; 
new BroadcastReceiver() { 
    public void onReceive(Context context, Intent intent) { 
     b[0] = peekService(context, intent); 
    } 
}.onReceiver(context, intent); 

IMyInterface i = IMyInterface.Stub.asInterface(b[0); 

ノート。

+0

これはハックです、bnutしかし、私の知る限りでは、BRはサービスからメッセージを取得する必要があり、これは、上出来ですまた、私はサービスがローカルでなければならないと仮定それを送り返したり、意図を使ってアクティビティに送ると、それはサービスにバインドするつもりではないので...そのメソッドを持つことは実際にBRのアイデアを破っています。 – codeScriber

4

ここで挑戦的な質問をすると、私は決して適切なものは得られません。答え、私はそれを自分で見つけなければなりません。

インテントの問題は、送信者のアドレスが重要でないネットワークでは、送信者がマルチキャストと並行しているため、送信者を取得できないことです。

もし私がsnderのUIDを取得したいのであれば、彼がローカルであっても "リモート"プロセスを作る必要があります。ブロードキャストIPCを使う代わりに、IBInderの実装でAIDLを使う必要があります。 Binderオブジェクトを取得したら、私のサービスgetCallingUid()を呼び出して呼び出し元のuidを取得できます。これにより、PackageManagerに公開証明書を与えるように要求できます(プロセス自体に問い合わせることなく、それをapkで事前に準備した一連の証明書と比較してください。

他の側の呼び出しアプリケーション(IDを送信している他のプロセス)は、bindService(service、conn、flags)メソッドを使用してバインドする必要があります。 このアプローチの欠点は時間のかかるプロセスです。バインドには時間がかかります。カーネルを通過する非同期呼び出しで、ローカルサービスにバインドするほど高速ではありません。さらに私はいくつかのアプリケーションを持っているかもしれないので、私の内部IDにアクセスを同期させる必要があるので、失敗しなかった最初のバインディングコールだけが設定され、私のIDになります。 マルチスレッドの問題を防ぐMessangerメソッドを使用できるかどうかを確認する必要があります。

これは他の人に役立つことを期待しています。

0

すでに述べたように、おそらく結合がこれに対する最良の解決策です。しかし、startActivityForResult()で起動したと仮定すると、BroadcastReceiverではなくActivityに切り替えてからgetCallingActivity()を使用することができます。 BroadcastReceiverのように、それは「サイレント」にするために、次のように

はあなたの活動を宣言します。

<activity 
    android:name=".FauxReceiver" 
    android:theme="@android:style/Theme.NoDisplay" 
    android:excludeFromRecents="true" 
    android:noHistory="true" 
> 
    <intent-filter> 
     ... 
    </intent-filter> 
</activity> 

インスピレーション:How to get the sender of an Intent?

+1

私たちは検証のためのライブラリ最も簡単なので、このテクニックを使って始める「インテント」の送信者と受信者。詳細はこちらhttps://dev.guardianproject.info/projects/trustedintents/wiki –

+0

@ Hans-ChristophSteinerよく見えます。コストがおそらく最小限に抑えられているため、(結果を必要とするだけでなく)すべてのインテント呼び出しに送信者を含めなかったのは奇妙です。 –

-1

私が送信したアプリケーションのパッケージ名を確認する方法を探していました。私のインテントフィルターで受け取ったインテント。インテントフィルタを処理するアプリケーションのアクティビティでは、インテント送信者がインテントエクストラフィールドにプロセスIDを含める必要があります。受信アクティビティは、関連するアプリケーションパッケージ名をActivityManagerから取得できます。

ここにStackOverflowをシフトしながら見つけたコードの例をいくつか示します。両方のアプリのために必要な

定数

のAppを受け
public static final String EXTRA_APP_ID; 
public static final String ACTION_VERIFY = "com.example.receivingapp.action.VERIFY"; 

活動を呼び出す

Intent verifyIntent = new Intent(); 
    verifyIntent.setAction(Consts.ACTION_VERIFY); 
    verifyIntent.putExtra(EXTRA_APP_ID, android.os.Process.myPid()); 
    // Verify that the intent will resolve to an activity 
    if (verifyIntent.resolveActivity(getPackageManager()) != null) { 
    startActivityForResult(verifyIntent, Consts.REQUEST_VERIFY); 
    } else { 
     Log.d(TAG, "Application not found."); 
    } 

マニフェスト

 <activity 
      android:name="com.example.receivingapp.ReceivingActivity" 
      android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="com.example.receivingapp.VERIFY" /> 
       <category android:name="android.intent.category.DEFAULT" /> 
      </intent-filter> 
     </activity> 

ReceivingActivity

if (getIntent().hasExtra(OnyxCoreConsts.EXTRA_APP_ID)) { 
    string appName = null; 
    // Resolve intent 
    if (getIntent().getAction().equals(ACTION_VERIFY) {  
     int appPid = getIntent().getIntExtra(EXTRA_APP_ID, -1); 
     if (-1 != mAppPid) { 
      appName = Utils.getAppNameByPID(mContext, mAppPid); 
     } 
     if (null != appName && !"".equalsIgnoreCase(appName)) { 
       // Do something with the application package name 
     } 
    } 
} 

Utilsのクラス

public static String getAppNameByPID(Context context, int pid){ 
     ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 

     for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { 
      if (processInfo.pid == pid) { 
       return processInfo.processName; 
      } 
     } 
     return ""; 
    } 
関連する問題