mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-07 18:40:19 -05:00
Fixes for passphrase cache implementation
This commit is contained in:
parent
4b8400685a
commit
979aad6589
@ -21,7 +21,6 @@ import java.security.Security;
|
|||||||
|
|
||||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.thialfihar.android.apg.helper.PGPMain;
|
import org.thialfihar.android.apg.helper.PGPMain;
|
||||||
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
@ -37,10 +36,6 @@ public class ApgApplication extends Application {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
/* Start passphrase cache service */
|
|
||||||
// TODO: not needed anymore!
|
|
||||||
// PassphraseCacheService.startCacheService(this);
|
|
||||||
|
|
||||||
// TODO: Do it better than this!
|
// TODO: Do it better than this!
|
||||||
// this initializes the database to be used in PGPMain
|
// this initializes the database to be used in PGPMain
|
||||||
PGPMain.initialize(this);
|
PGPMain.initialize(this);
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.thialfihar.android.apg.service;
|
|
||||||
|
|
||||||
public class CachedPassphrase {
|
|
||||||
private final long timestamp;
|
|
||||||
private final String passphrase;
|
|
||||||
|
|
||||||
public CachedPassphrase(long timestamp, String passPhrase) {
|
|
||||||
super();
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
this.passphrase = passPhrase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassphrase() {
|
|
||||||
return passphrase;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hc1 = (int) (this.timestamp & 0xffffffff);
|
|
||||||
int hc2 = (this.passphrase == null ? 0 : this.passphrase.hashCode());
|
|
||||||
return (hc1 + hc2) * hc2 + hc1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (!(other instanceof CachedPassphrase)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CachedPassphrase o = (CachedPassphrase) other;
|
|
||||||
if (timestamp != o.timestamp) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passphrase != o.passphrase) {
|
|
||||||
if (passphrase == null || o.passphrase == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!passphrase.equals(o.passphrase)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "(" + timestamp + ", *******)";
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.thialfihar.android.apg.service;
|
package org.thialfihar.android.apg.service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
@ -35,10 +36,11 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class PassphraseCacheService extends Service {
|
public class PassphraseCacheService extends Service {
|
||||||
|
public static final String TAG = Constants.TAG + ": PassphraseCacheService";
|
||||||
|
|
||||||
public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX
|
public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX
|
||||||
+ "PASSPHRASE_CACHE_SERVICE";
|
+ "PASSPHRASE_CACHE_SERVICE";
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
// TODO: This is static to be easily retrieved by getCachedPassphrase()
|
// TODO: This is static to be easily retrieved by getCachedPassphrase()
|
||||||
// To avoid static we would need a messenger from the service back to the activity?
|
// To avoid static we would need a messenger from the service back to the activity?
|
||||||
private static HashMap<Long, CachedPassphrase> mPassphraseCache = new HashMap<Long, CachedPassphrase>();
|
private static HashMap<Long, String> mPassphraseCache = new HashMap<Long, String>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This caches a new passphrase by sending a new command to the service. An android service is
|
* This caches a new passphrase by sending a new command to the service. An android service is
|
||||||
@ -65,7 +67,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
* @param passphrase
|
* @param passphrase
|
||||||
*/
|
*/
|
||||||
public static void addCachedPassphrase(Context context, long keyId, String passphrase) {
|
public static void addCachedPassphrase(Context context, long keyId, String passphrase) {
|
||||||
Log.d(Constants.TAG, "cacheNewPassphrase() for " + keyId);
|
Log.d(TAG, "cacheNewPassphrase() for " + keyId);
|
||||||
|
|
||||||
Intent intent = new Intent(context, PassphraseCacheService.class);
|
Intent intent = new Intent(context, PassphraseCacheService.class);
|
||||||
intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
|
intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
|
||||||
@ -98,14 +100,15 @@ public class PassphraseCacheService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get cached passphrase
|
// get cached passphrase
|
||||||
CachedPassphrase cpp = mPassphraseCache.get(realId);
|
String cachedPassphrase = mPassphraseCache.get(realId);
|
||||||
if (cpp == null) {
|
if (cachedPassphrase == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// set it again to reset the cache life cycle
|
// set it again to reset the cache life cycle
|
||||||
addCachedPassphrase(context, realId, cpp.getPassphrase());
|
Log.d(TAG, "Cache passphrase again when getting it!");
|
||||||
|
addCachedPassphrase(context, realId, cachedPassphrase);
|
||||||
|
|
||||||
return cpp.getPassphrase();
|
return cachedPassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,6 +123,8 @@ public class PassphraseCacheService extends Service {
|
|||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
|
|
||||||
|
Log.d(TAG, "Received broadcast...");
|
||||||
|
|
||||||
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(context, keyId);
|
timeout(context, keyId);
|
||||||
@ -129,7 +134,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
|
filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
|
||||||
LocalBroadcastManager.getInstance(this).registerReceiver(mIntentReceiver, filter);
|
registerReceiver(mIntentReceiver, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +156,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService created!");
|
Log.d(TAG, "onCreate()");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,7 +164,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService started");
|
Log.d(TAG, "onStartCommand()");
|
||||||
|
|
||||||
// register broadcastreceiver
|
// register broadcastreceiver
|
||||||
registerReceiver();
|
registerReceiver();
|
||||||
@ -169,14 +174,13 @@ public class PassphraseCacheService extends Service {
|
|||||||
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
||||||
String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
|
String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
|
||||||
|
|
||||||
Log.d(Constants.TAG, "received intent with keyId: " + keyId + ", ttl: " + ttl);
|
Log.d(TAG, "Received intent in onStartCommand() with keyId: " + keyId + ", ttl: " + ttl);
|
||||||
|
|
||||||
// add keyId and passphrase to memory
|
// add keyId and passphrase to memory
|
||||||
mPassphraseCache.put(keyId,
|
mPassphraseCache.put(keyId, passphrase);
|
||||||
new CachedPassphrase(System.currentTimeMillis(), passphrase));
|
|
||||||
|
|
||||||
// register new alarm with keyId for this passphrase
|
// register new alarm with keyId for this passphrase
|
||||||
long triggerTime = System.currentTimeMillis() + ttl;
|
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, keyId));
|
am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId));
|
||||||
}
|
}
|
||||||
@ -191,23 +195,23 @@ public class PassphraseCacheService extends Service {
|
|||||||
* @param keyId
|
* @param keyId
|
||||||
*/
|
*/
|
||||||
private void timeout(Context context, long keyId) {
|
private void timeout(Context context, long keyId) {
|
||||||
Log.d(Constants.TAG, "Timeout of " + keyId);
|
|
||||||
|
|
||||||
// remove passphrase corresponding to keyId from memory
|
// remove passphrase corresponding to keyId from memory
|
||||||
mPassphraseCache.remove(keyId);
|
mPassphraseCache.remove(keyId);
|
||||||
|
|
||||||
|
Log.d(TAG, "Timeout of " + keyId + ", removed from memory!");
|
||||||
|
|
||||||
// stop whole service if no cached passphrases remaining
|
// stop whole service if no cached passphrases remaining
|
||||||
if (mPassphraseCache.isEmpty()) {
|
if (mPassphraseCache.isEmpty()) {
|
||||||
Log.d(Constants.TAG, "No passphrases remaining in memory, stopping service!");
|
Log.d(TAG, "No passphrases remaining in memory, stopping service!");
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService destroyed!");
|
Log.d(TAG, "onDestroy()");
|
||||||
|
|
||||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mIntentReceiver);
|
unregisterReceiver(mIntentReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PassphraseCacheBinder extends Binder {
|
public class PassphraseCacheBinder extends Binder {
|
||||||
|
@ -21,7 +21,6 @@ import org.spongycastle.openpgp.PGPEncryptedData;
|
|||||||
import org.thialfihar.android.apg.Constants;
|
import org.thialfihar.android.apg.Constants;
|
||||||
import org.thialfihar.android.apg.Id;
|
import org.thialfihar.android.apg.Id;
|
||||||
import org.thialfihar.android.apg.helper.Preferences;
|
import org.thialfihar.android.apg.helper.Preferences;
|
||||||
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
|
||||||
import org.thialfihar.android.apg.ui.widget.IntegerListPreference;
|
import org.thialfihar.android.apg.ui.widget.IntegerListPreference;
|
||||||
import org.thialfihar.android.apg.R;
|
import org.thialfihar.android.apg.R;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user