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.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;
private enum TimeoutMode {
NEVER, TTL, LOCK
}
public CachedPassphrase(Passphrase passphrase, String primaryUserID) {
setPassphrase(passphrase);
setPrimaryUserID(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 String getPrimaryUserID() {
return primaryUserID;
static CachedPassphrase getPassphraseNoTimeout(Passphrase passphrase, String primaryUserId) {
return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.NEVER, null);
}
public Passphrase getPassphrase() {
return passphrase;
static CachedPassphrase getPassphraseTtlTimeout(Passphrase passphrase, String primaryUserId, long timeoutTime) {
return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.TTL, timeoutTime);
}
public void setPrimaryUserID(String primaryUserID) {
this.primaryUserID = primaryUserID;
}
public void setPassphrase(Passphrase passphrase) {
this.passphrase = passphrase;
static CachedPassphrase getPassphraseLock(Passphrase passphrase, String primaryUserId) {
return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.LOCK, null);
}
}
}