diff options
author | Dominik Schürmann <dominik@dominikschuermann.de> | 2013-05-28 22:48:42 +0200 |
---|---|---|
committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2013-05-28 22:48:42 +0200 |
commit | 215864a33ef2023e30a72f831ebea3a6c24ebbc1 (patch) | |
tree | 74912418a6d37c3e7af7d61b7cc45d587b4e575e /OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java | |
parent | b221c0c9051d7dea697aff7b3167fca69eb1f4f8 (diff) | |
download | open-keychain-215864a33ef2023e30a72f831ebea3a6c24ebbc1.tar.gz open-keychain-215864a33ef2023e30a72f831ebea3a6c24ebbc1.tar.bz2 open-keychain-215864a33ef2023e30a72f831ebea3a6c24ebbc1.zip |
Process safe implementation of PassphraseCacheService, First test for crypto provider
Diffstat (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java')
-rw-r--r-- | OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java | 169 |
1 files changed, 128 insertions, 41 deletions
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index f29514e79..d11b8e92a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,27 +39,39 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; import android.util.Log; public class PassphraseCacheService extends Service { public static final String TAG = Constants.TAG + ": PassphraseCacheService"; + public static final String ACTION_PASSPHRASE_CACHE_ADD = Constants.INTENT_PREFIX + + "PASSPHRASE_CACHE_ADD"; + public static final String ACTION_PASSPHRASE_CACHE_GET = Constants.INTENT_PREFIX + + "PASSPHRASE_CACHE_GET"; + public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX - + "PASSPHRASE_CACHE_SERVICE"; + + "PASSPHRASE_CACHE_BROADCAST"; public static final String EXTRA_TTL = "ttl"; public static final String EXTRA_KEY_ID = "keyId"; public static final String EXTRA_PASSPHRASE = "passphrase"; + public static final String EXTRA_MESSENGER = "messenger"; private static final int REQUEST_ID = 0; private static final long DEFAULT_TTL = 15; private BroadcastReceiver mIntentReceiver; - // This is static to be easily retrieved by getCachedPassphrase() without the need of callback - // functions - private static HashMap<Long, String> mPassphraseCache = new HashMap<Long, String>(); + private HashMap<Long, String> mPassphraseCache = new HashMap<Long, String>(); + + Context mContext; /** * This caches a new passphrase by sending a new command to the service. An android service is @@ -74,6 +86,7 @@ public class PassphraseCacheService extends Service { Log.d(TAG, "cacheNewPassphrase() for " + keyId); Intent intent = new Intent(context, PassphraseCacheService.class); + intent.setAction(ACTION_PASSPHRASE_CACHE_ADD); intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl()); intent.putExtra(EXTRA_PASSPHRASE, passphrase); intent.putExtra(EXTRA_KEY_ID, keyId); @@ -82,17 +95,65 @@ public class PassphraseCacheService extends Service { } /** - * Gets a cached passphrase from memory + * Gets a cached passphrase from memory, blocking method * * @param context * @param keyId * @return */ public static String getCachedPassphrase(Context context, long keyId) { + Log.d(TAG, "getCachedPassphrase() get masterKeyId for " + keyId); + Intent intent = new Intent(context, PassphraseCacheService.class); + intent.setAction(ACTION_PASSPHRASE_CACHE_GET); + + final Object mutex = new Object(); + final Bundle returnBundle = new Bundle(); + + HandlerThread handlerThread = new HandlerThread("getPassphrase"); + handlerThread.start(); + Handler returnHandler = new Handler(handlerThread.getLooper()) { + @Override + public void handleMessage(Message message) { + if (message.obj != null) { + String passphrase = ((Bundle) message.obj).getString(EXTRA_PASSPHRASE); + returnBundle.putString(EXTRA_PASSPHRASE, passphrase); + } + synchronized (mutex) { + mutex.notify(); + } + getLooper().quit(); + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + intent.putExtra(EXTRA_KEY_ID, keyId); + intent.putExtra(EXTRA_MESSENGER, messenger); + // send intent to this service + context.startService(intent); + + // Wait on mutex until passphrase is returned to handlerThread + synchronized (mutex) { + try { + mutex.wait(3000); + } catch (InterruptedException e) { + } + } + + if (returnBundle.containsKey(EXTRA_PASSPHRASE)) { + return returnBundle.getString(EXTRA_PASSPHRASE); + } else { + return null; + } + } + + private String getCachedPassphraseImpl(long keyId) { + Log.d(TAG, "getCachedPassphraseImpl() get masterKeyId for " + keyId); + // try to get master key id which is used as an identifier for cached passphrases long masterKeyId = keyId; if (masterKeyId != Id.key.symmetric) { - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, keyId); + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(this, keyId); if (keyRing == null) { return null; } @@ -102,22 +163,24 @@ public class PassphraseCacheService extends Service { } masterKeyId = masterKey.getKeyID(); } + Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId" + masterKeyId); // get cached passphrase String cachedPassphrase = mPassphraseCache.get(masterKeyId); if (cachedPassphrase == null) { + // TODO: fix! // check if secret key has a passphrase - if (!hasPassphrase(context, masterKeyId)) { - // cache empty passphrase - addCachedPassphrase(context, masterKeyId, ""); - return ""; - } else { - return null; - } + // if (!hasPassphrase(context, masterKeyId)) { + // // cache empty passphrase + // addCachedPassphrase(context, masterKeyId, ""); + // return ""; + // } else { + return null; + // } } // set it again to reset the cache life cycle Log.d(TAG, "Cache passphrase again when getting it!"); - addCachedPassphrase(context, masterKeyId, cachedPassphrase); + addCachedPassphrase(this, masterKeyId, cachedPassphrase); return cachedPassphrase; } @@ -196,11 +259,6 @@ public class PassphraseCacheService extends Service { return sender; } - @Override - public void onCreate() { - Log.d(TAG, "onCreate()"); - } - /** * Executed when service is started by intent */ @@ -211,20 +269,41 @@ public class PassphraseCacheService extends Service { // register broadcastreceiver registerReceiver(); - if (intent != null) { - long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL); - long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); - String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE); - - Log.d(TAG, "Received intent in onStartCommand() with keyId: " + keyId + ", ttl: " + ttl); - - // add keyId and passphrase to memory - mPassphraseCache.put(keyId, passphrase); - - // register new alarm with keyId for this passphrase - long triggerTime = new Date().getTime() + (ttl * 1000); - AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); - am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId)); + if (intent != null && intent.getAction() != null) { + if (ACTION_PASSPHRASE_CACHE_ADD.equals(intent.getAction())) { + long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL); + long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); + String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE); + + Log.d(TAG, + "Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: " + + keyId + ", ttl: " + ttl); + + // add keyId and passphrase to memory + mPassphraseCache.put(keyId, passphrase); + + // register new alarm with keyId for this passphrase + long triggerTime = new Date().getTime() + (ttl * 1000); + AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); + am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId)); + } else if (ACTION_PASSPHRASE_CACHE_GET.equals(intent.getAction())) { + long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); + Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER); + + String passphrase = getCachedPassphraseImpl(keyId); + + Message msg = Message.obtain(); + Bundle bundle = new Bundle(); + bundle.putString(EXTRA_PASSPHRASE, passphrase); + msg.obj = bundle; + try { + messenger.send(msg); + } catch (RemoteException e) { + Log.e(Constants.TAG, "Sending message failed", e); + } + } else { + Log.e(Constants.TAG, "Intent or Intent Action not supported!"); + } } return START_STICKY; @@ -240,7 +319,7 @@ public class PassphraseCacheService extends Service { // remove passphrase corresponding to keyId from memory mPassphraseCache.remove(keyId); - Log.d(TAG, "Timeout of " + keyId + ", removed from memory!"); + Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!"); // stop whole service if no cached passphrases remaining if (mPassphraseCache.isEmpty()) { @@ -250,12 +329,25 @@ public class PassphraseCacheService extends Service { } @Override + public void onCreate() { + super.onCreate(); + mContext = this; + Log.d(Constants.TAG, "PassphraseCacheService, onCreate()"); + } + + @Override public void onDestroy() { - Log.d(TAG, "onDestroy()"); + super.onDestroy(); + Log.d(Constants.TAG, "PassphraseCacheService, onDestroy()"); unregisterReceiver(mIntentReceiver); } + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + public class PassphraseCacheBinder extends Binder { public PassphraseCacheService getService() { return PassphraseCacheService.this; @@ -264,9 +356,4 @@ public class PassphraseCacheService extends Service { private final IBinder mBinder = new PassphraseCacheBinder(); - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - }
\ No newline at end of file |