From 52ab77d2a41d8d2e61cc864dbfd63dd1185a184b Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 18 Nov 2015 19:13:21 +0100 Subject: passcache: add support for clear on screen lock (ttl == 0) --- .../keychain/service/PassphraseCacheService.java | 106 ++++++++++++++------- 1 file changed, 70 insertions(+), 36 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 82198120d..be14f1586 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -27,6 +27,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -93,7 +95,7 @@ public class PassphraseCacheService extends Service { public static final String EXTRA_MESSENGER = "messenger"; public static final String EXTRA_USER_ID = "user_id"; - private static final int DEFAULT_TTL = 15; + private static final int DEFAULT_TTL = 0; private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1; private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2; @@ -237,7 +239,7 @@ public class PassphraseCacheService extends Service { if (cachedPassphrase == null) { return null; } - return cachedPassphrase.getPassphrase(); + return cachedPassphrase.mPassphrase; } // try to get master key id which is used as an identifier for cached passphrases @@ -284,7 +286,7 @@ public class PassphraseCacheService extends Service { } - return cachedPassphrase.getPassphrase(); + return cachedPassphrase.mPassphrase; } /** @@ -303,13 +305,18 @@ public class PassphraseCacheService extends Service { if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) { long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); - timeout(keyId); + removeTimeoutedPassphrase(keyId); + } + + if (action.equals(Intent.ACTION_SCREEN_OFF)) { + removeScreenLockPassphrases(); } } }; IntentFilter filter = new IntentFilter(); filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE); + filter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(mIntentReceiver, filter); } } @@ -337,35 +344,39 @@ public class PassphraseCacheService extends Service { return START_STICKY; } - // register broadcastreceiver - registerReceiver(); - String action = intent.getAction(); switch (action) { case ACTION_PASSPHRASE_CACHE_ADD: { - long ttl = intent.getIntExtra(EXTRA_TTL, DEFAULT_TTL); long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1); long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1); + long timeoutTime = intent.getIntExtra(EXTRA_TTL, DEFAULT_TTL); Passphrase passphrase = intent.getParcelableExtra(EXTRA_PASSPHRASE); String primaryUserID = intent.getStringExtra(EXTRA_USER_ID); Log.d(Constants.TAG, "PassphraseCacheService: Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with masterkeyId: " - + masterKeyId + ", subKeyId: " + subKeyId + ", ttl: " + ttl + ", usrId: " + primaryUserID + + masterKeyId + ", subKeyId: " + subKeyId + ", ttl: " + timeoutTime + ", usrId: " + primaryUserID ); // if we don't cache by specific subkey id, or the requested subkey is the master key, // just add master key id to the cache, otherwise, add this specific subkey to the cache long referenceKeyId = Preferences.getPreferences(mContext).getPassphraseCacheSubs() ? subKeyId : masterKeyId; - mPassphraseCache.put(referenceKeyId, new CachedPassphrase(passphrase, primaryUserID)); - if (ttl > 0) { + + CachedPassphrase cachedPassphrase; + if (timeoutTime == 0) { + cachedPassphrase = CachedPassphrase.getPassphraseLock(passphrase, primaryUserID); + } else { + cachedPassphrase = CachedPassphrase.getPassphraseTtlTimeout(passphrase, primaryUserID, timeoutTime); + // 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, referenceKeyId)); + am.set(AlarmManager.RTC_WAKEUP, timeoutTime, buildIntent(this, referenceKeyId)); } + + mPassphraseCache.put(referenceKeyId, cachedPassphrase); + break; } case ACTION_PASSPHRASE_CACHE_GET: { @@ -435,16 +446,14 @@ public class PassphraseCacheService extends Service { return START_STICKY; } - /** - * Called when one specific passphrase for keyId timed out - */ - private void timeout(long keyId) { + /** Called when one specific passphrase for keyId timed out. */ + private void removeTimeoutedPassphrase(long keyId) { CachedPassphrase cPass = mPassphraseCache.get(keyId); if (cPass != null) { - if (cPass.getPassphrase() != null) { + if (cPass.mPassphrase != null) { // clean internal char[] from memory! - cPass.getPassphrase().removeFromMemory(); + cPass.mPassphrase.removeFromMemory(); } // remove passphrase object mPassphraseCache.remove(keyId); @@ -455,6 +464,24 @@ public class PassphraseCacheService extends Service { updateService(); } + private void removeScreenLockPassphrases() { + + for (int i = 0; i < mPassphraseCache.size(); ) { + CachedPassphrase cPass = mPassphraseCache.valueAt(i); + if (cPass.mTimeoutMode == TimeoutMode.LOCK) { + // remove passphrase object + mPassphraseCache.removeAt(i); + continue; + } + // only do this if we didn't remove at, which continues loop by reducing size! + i += 1; + } + + Log.d(Constants.TAG, "PassphraseCacheService Removing all cached-until-lock passphrases from memory!"); + + updateService(); + } + private void updateService() { if (mPassphraseCache.size() > 0) { startForeground(Constants.Notification.PASSPHRASE_CACHE, getNotification()); @@ -479,7 +506,7 @@ public class PassphraseCacheService extends Service { // Moves events into the big view for (int i = 0; i < mPassphraseCache.size(); i++) { - inboxStyle.addLine(mPassphraseCache.valueAt(i).getPrimaryUserID()); + inboxStyle.addLine(mPassphraseCache.valueAt(i).mPrimaryUserId); } // Moves the big view style object into the notification object. @@ -512,6 +539,8 @@ public class PassphraseCacheService extends Service { super.onCreate(); mContext = this; Log.d(Constants.TAG, "PassphraseCacheService, onCreate()"); + + registerReceiver(); } @Override @@ -535,29 +564,34 @@ public class PassphraseCacheService extends Service { private final IBinder mBinder = new PassphraseCacheBinder(); - public class CachedPassphrase { - private String primaryUserID; - private Passphrase passphrase; - - public CachedPassphrase(Passphrase passphrase, String primaryUserID) { - setPassphrase(passphrase); - setPrimaryUserID(primaryUserID); - } + private enum TimeoutMode { + NEVER, TTL, LOCK + } - public String getPrimaryUserID() { - return primaryUserID; + private static class CachedPassphrase { + private String mPrimaryUserId; + private Passphrase mPassphrase; + private TimeoutMode mTimeoutMode; + private Long mTimeoutTime; + + private CachedPassphrase(Passphrase passphrase, String primaryUserId, TimeoutMode timeoutMode, Long timeoutTime) { + mPassphrase = passphrase; + mPrimaryUserId = primaryUserId; + mTimeoutMode = timeoutMode; + mTimeoutTime = timeoutTime; } - public Passphrase getPassphrase() { - return passphrase; + static CachedPassphrase getPassphraseNoTimeout(Passphrase passphrase, String primaryUserId) { + return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.NEVER, null); } - public void setPrimaryUserID(String primaryUserID) { - this.primaryUserID = primaryUserID; + static CachedPassphrase getPassphraseTtlTimeout(Passphrase passphrase, String primaryUserId, long timeoutTime) { + return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.TTL, timeoutTime); } - public void setPassphrase(Passphrase passphrase) { - this.passphrase = passphrase; + static CachedPassphrase getPassphraseLock(Passphrase passphrase, String primaryUserId) { + return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.LOCK, null); } } + } -- cgit v1.2.3