2013-03-20 16 views
5

Pracuję w firmie, która produkuje kilka aplikacji, nie wszystkie te aplikacje mają ten sam podpis lub więcej, mamy na razie co najmniej 5-6 certyfikatów aplikacji.Android: sprawdź tożsamość intencyjnego nadawcy

Próbowaliśmy stworzyć mechanizm, w którym wszystkie aplikacje Companii na tym samym urządzeniu mają takie same funkcje, Na przykład, jeśli użytkownik zainstalował aplikację A z rynku i nie zainstalował żadnej aplikacji, zostanie wygenerowany nowy identyfikator, jeśli teraz instaluje aplikację A, aplikacja B powinna mieć ten sam identyfikator co aplikacja A (identyfikator to tylko wygenerowany typ UUID nr 4) itp.

Używamy transmisji w tej chwili i tylko aplikacje z naszą zgodą mogą odbierać to nadawać i odsyłać identyfikator z inną transmisją (tym razem wyraźnie). Transmisja i odpowiedzi są chronione za naszym pozwoleniem przy użyciu poziomu podpisu, co oczywiście nie pomaga, ponieważ mamy więcej niż jeden podpis.

Próbowałem napisać transmisję intencji i odzyskać, która może mieć swój własny mechanizm ochrony, który nie będzie ograniczony tylko do jednego podpisu, ale kilka, problem polega na tym, że rzeczy takie jak Binder.getSenderUID() nie działają dla transmisji i dostaję mój własny uid. Wygląda na to, że nie mam sposobu, aby uzyskać tożsamość mojego sndera, chyba że sam napisze swój identyfikator w intencji, której NIE jest czymś, co mogę zaufać, ponieważ może być łatwo sfałszowany. Korzystanie z szyfrowania wymaga, aby aplikacje zawierały klucz, który nie jest jeszcze raz zabezpieczony. Zwrócenie się do serwera w celu sprawdzenia poprawności zajmuje zbyt dużo czasu, a na urządzeniach mobilnych nie gwarantuje się sukcesu, ponieważ nie ma 100% pewności, że sieć jest podłączona.

Ktoś ma pojęcie, w jaki sposób można uzyskać potwierdzenie/bezpieczną wiadomość z jednej aplikacji do drugiej? (Wszystkie moje aplikacje, ale mogą mieć różne podpisy).

Odpowiedz

2

Przepraszamy za opóźnienie w odpowiedzi ...

Bind wymaga czasu, a co ważniejsze, jego asynchronicznym. Istnieje jednak sposób na utworzenie powiązania synchronicznego - zakładając oczywiście, że usługa, z którą próbujesz się skontaktować, jest już uruchomiona w tym czasie. Android dozwolony dla tego więcej dla BroadcastReceivers (które są asynchroniczne w naturze, a zatem nie mogą używać normalnej bindService) a BroadcastReceiver ma metodę "peekService".

Jeśli chcesz używać go bez słuchania audycji, można by robić:

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); 

pamiętać, że nie wiążą się z usługą, więc upewnij się, aby zerknąć na każdym użyciu.

+0

jest to hack, bnut to jest cholernie dobry, również Zakładam, że usługa musi być lokalny, jednak o ile wiem, BR powinien być coraz wiadomości z serwisu i wysłać go z powrotem lub wysłać do działania za pomocą intencji, nie jest przeznaczone do wiązania usługi ... tak, że ta metoda naprawdę łamie ideę BR ... – codeScriber

4

Jak zawsze z trudnym pytaniem tutaj nigdy nie dostaję właściwego, jeśli KAŻDEGO! odpowiedź, więc jestem zmuszony sam to znaleźć.

Problem z zamierzeniami polega na tym, że nie można uzyskać nadawcy, ponieważ jest on równoległy do ​​mulicast w sieci, w której adres nadawcy nie jest ważny.

Jeśli chcę uzyskać UID Sndera, muszę wykonać "zdalny" proces, nawet jeśli jest on lokalny, zamiast korzystania z IPC transmisji potrzebuję użyć AIDL z implementacją IBInder. Kiedy już posiadam obiekt Binder mogę wywołać w mojej usłudze getCallingUid() i pobrać identyfikator rozmówcy, to pozwoli mi poprosić PackageManager o przyznanie mi publicznego certyfikatu (bez zadawania samego procesu, pytam OS) i porównaj to z zestawem certyfikatów, które przygotowałem wcześniej w pakiecie APK.

Aplikacja wywołująca po drugiej stronie (drugi proces, który wysyła mi swój identyfikator) musi jedynie użyć metody bindService (service, conn, flags), aby się do mnie połączyć. Wadą takiego podejścia jest czasochłonny proces, Bind wymaga czasu, jest to połączenie asynchroniczne, które przechodzi przez jądro i nie jest tak szybkie jak powiązanie z lokalną usługą. Ponadto, ponieważ mogę mieć kilka aplikacji, muszę zsynchronizować dostęp do mojego wewnętrznego ID, więc tylko pierwsze wywołanie, które nie zawiodło, ustawi się i ID dla mnie. Nadal muszę sprawdzić, czy mogę użyć metody Messanger, która zapobiega problemom z wieloma wątkami.

Nadzieje, że to pomaga komuś innemu.

0

Jak już stwierdzono, wiązanie jest prawdopodobnie najlepszym rozwiązaniem. Możesz jednak rozważyć przejście na działanie, a nie na BroadcastReceiver, wtedy możesz użyć getCallingActivity(), zakładając, że uruchomiłeś z startActivityForResult().

stwierdzenie Ci aktywny w następujący sposób, aby to „ciche” jak BroadcastReceiver:

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

Inspiracja: How to get the sender of an Intent?

+1

Pracujemy nad biblioteką do weryfikacji nadawca i odbiorca 'Intent's, który używa tej techniki na początku, ponieważ jest najprostszy. Możesz dowiedzieć się więcej tutaj https://dev.guardianproject.info/projects/trustedintents/wiki –

+0

@ Hans-ChristophSteiner Wygląda dobrze. To dziwne, że nie uwzględnili nadawcy we wszystkich wywołaniach Intencji (nie tylko tych wymagających wyniku), ponieważ koszt prawdopodobnie byłby minimalny. –

-1

szukałem sposobu, aby sprawdzić nazwę pakietu aplikacji, która wysłała zamiar odebrany przez mój filtr intencji. Ta aktywność w mojej aplikacji, która obsługuje filtr intencji, wymaga, aby docelowy nadawca uwzględnił swój identyfikator procesu w polu Intent Extras. Moja aktywność odbiorcza może następnie pobrać skojarzoną nazwę pakietu aplikacji z ActivityManager.

Oto przykład kodu, który znalazłem podczas przesuwania przez StackOverflow.

stałych potrzebnych do obu Apps

public static final String EXTRA_APP_ID; 
public static final String ACTION_VERIFY = "com.example.receivingapp.action.VERIFY"; 

Wywoływanie aktywności

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."); 
    } 

otrzymujących App

Manifest

 <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 klasa

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 ""; 
    } 
Powiązane problemy