passcache: add support for clear on screen lock (ttl == 0)

This commit is contained in:
Vincent Breitmoser
2015-11-18 19:13:21 +01:00
parent a75b26be66
commit 52ab77d2a4

View File

@@ -27,6 +27,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.Binder; import android.os.Binder;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; 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_MESSENGER = "messenger";
public static final String EXTRA_USER_ID = "user_id"; 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_OKAY = 1;
private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2; private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2;
@@ -237,7 +239,7 @@ public class PassphraseCacheService extends Service {
if (cachedPassphrase == null) { if (cachedPassphrase == null) {
return null; return null;
} }
return cachedPassphrase.getPassphrase(); return cachedPassphrase.mPassphrase;
} }
// try to get master key id which is used as an identifier for cached passphrases // 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)) { if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) {
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
timeout(keyId); removeTimeoutedPassphrase(keyId);
}
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
removeScreenLockPassphrases();
} }
} }
}; };
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE); filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mIntentReceiver, filter); registerReceiver(mIntentReceiver, filter);
} }
} }
@@ -337,35 +344,39 @@ public class PassphraseCacheService extends Service {
return START_STICKY; return START_STICKY;
} }
// register broadcastreceiver
registerReceiver();
String action = intent.getAction(); String action = intent.getAction();
switch (action) { switch (action) {
case ACTION_PASSPHRASE_CACHE_ADD: { case ACTION_PASSPHRASE_CACHE_ADD: {
long ttl = intent.getIntExtra(EXTRA_TTL, DEFAULT_TTL);
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1); long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1); long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1);
long timeoutTime = intent.getIntExtra(EXTRA_TTL, DEFAULT_TTL);
Passphrase passphrase = intent.getParcelableExtra(EXTRA_PASSPHRASE); Passphrase passphrase = intent.getParcelableExtra(EXTRA_PASSPHRASE);
String primaryUserID = intent.getStringExtra(EXTRA_USER_ID); String primaryUserID = intent.getStringExtra(EXTRA_USER_ID);
Log.d(Constants.TAG, Log.d(Constants.TAG,
"PassphraseCacheService: Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with masterkeyId: " "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, // 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 // just add master key id to the cache, otherwise, add this specific subkey to the cache
long referenceKeyId = long referenceKeyId =
Preferences.getPreferences(mContext).getPassphraseCacheSubs() ? subKeyId : masterKeyId; 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 // register new alarm with keyId for this passphrase
long triggerTime = new Date().getTime() + (ttl * 1000);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); 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; break;
} }
case ACTION_PASSPHRASE_CACHE_GET: { case ACTION_PASSPHRASE_CACHE_GET: {
@@ -435,16 +446,14 @@ public class PassphraseCacheService extends Service {
return START_STICKY; return START_STICKY;
} }
/** /** Called when one specific passphrase for keyId timed out. */
* Called when one specific passphrase for keyId timed out private void removeTimeoutedPassphrase(long keyId) {
*/
private void timeout(long keyId) {
CachedPassphrase cPass = mPassphraseCache.get(keyId); CachedPassphrase cPass = mPassphraseCache.get(keyId);
if (cPass != null) { if (cPass != null) {
if (cPass.getPassphrase() != null) { if (cPass.mPassphrase != null) {
// clean internal char[] from memory! // clean internal char[] from memory!
cPass.getPassphrase().removeFromMemory(); cPass.mPassphrase.removeFromMemory();
} }
// remove passphrase object // remove passphrase object
mPassphraseCache.remove(keyId); mPassphraseCache.remove(keyId);
@@ -455,6 +464,24 @@ public class PassphraseCacheService extends Service {
updateService(); 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() { private void updateService() {
if (mPassphraseCache.size() > 0) { if (mPassphraseCache.size() > 0) {
startForeground(Constants.Notification.PASSPHRASE_CACHE, getNotification()); startForeground(Constants.Notification.PASSPHRASE_CACHE, getNotification());
@@ -479,7 +506,7 @@ public class PassphraseCacheService extends Service {
// Moves events into the big view // Moves events into the big view
for (int i = 0; i < mPassphraseCache.size(); i++) { 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. // Moves the big view style object into the notification object.
@@ -512,6 +539,8 @@ public class PassphraseCacheService extends Service {
super.onCreate(); super.onCreate();
mContext = this; mContext = this;
Log.d(Constants.TAG, "PassphraseCacheService, onCreate()"); Log.d(Constants.TAG, "PassphraseCacheService, onCreate()");
registerReceiver();
} }
@Override @Override
@@ -535,29 +564,34 @@ public class PassphraseCacheService extends Service {
private final IBinder mBinder = new PassphraseCacheBinder(); private final IBinder mBinder = new PassphraseCacheBinder();
public class CachedPassphrase { private enum TimeoutMode {
private String primaryUserID; NEVER, TTL, LOCK
private Passphrase passphrase; }
public CachedPassphrase(Passphrase passphrase, String primaryUserID) { private static class CachedPassphrase {
setPassphrase(passphrase); private String mPrimaryUserId;
setPrimaryUserID(primaryUserID); 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 String getPrimaryUserID() { static CachedPassphrase getPassphraseNoTimeout(Passphrase passphrase, String primaryUserId) {
return primaryUserID; return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.NEVER, null);
} }
public Passphrase getPassphrase() { static CachedPassphrase getPassphraseTtlTimeout(Passphrase passphrase, String primaryUserId, long timeoutTime) {
return passphrase; return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.TTL, timeoutTime);
} }
public void setPrimaryUserID(String primaryUserID) { static CachedPassphrase getPassphraseLock(Passphrase passphrase, String primaryUserId) {
this.primaryUserID = primaryUserID; return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.LOCK, null);
}
public void setPassphrase(Passphrase passphrase) {
this.passphrase = passphrase;
} }
} }
} }