diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java')
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java | 121 |
1 files changed, 98 insertions, 23 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index bf56417e9..d9ef4f3c8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -26,6 +26,7 @@ import android.content.OperationApplicationException; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; +import android.support.annotation.NonNull; import android.support.v4.util.LongSparseArray; import org.spongycastle.bcpg.CompressionAlgorithmTags; @@ -38,7 +39,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; -import org.sufficientlysecure.keychain.operations.ImportExportOperation; +import org.sufficientlysecure.keychain.operations.ImportOperation; import org.sufficientlysecure.keychain.operations.results.ConsolidateResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; @@ -49,7 +50,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.PgpConstants; +import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; @@ -61,6 +62,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; +import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.util.IterableIterator; @@ -81,6 +84,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; /** * This class contains high level methods for database access. Despite its @@ -648,10 +652,6 @@ public class ProviderHelper { UserPacketItem item = uids.get(userIdRank); operations.add(buildUserIdOperations(masterKeyId, item, userIdRank)); - if (item.selfCert == null) { - throw new AssertionError("User ids MUST be self-certified at this point!!"); - } - if (item.selfRevocation != null) { operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfRevocation, Certs.VERIFIED_SELF)); @@ -659,6 +659,10 @@ public class ProviderHelper { continue; } + if (item.selfCert == null) { + throw new AssertionError("User ids MUST be self-certified at this point!!"); + } + operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfCert, selfCertsAreTrusted ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF)); @@ -684,6 +688,36 @@ public class ProviderHelper { mIndent -= 1; } + // before deleting key, retrieve it's last updated time + final int INDEX_MASTER_KEY_ID = 0; + final int INDEX_LAST_UPDATED = 1; + Cursor lastUpdatedCursor = mContentResolver.query( + UpdatedKeys.CONTENT_URI, + new String[]{ + UpdatedKeys.MASTER_KEY_ID, + UpdatedKeys.LAST_UPDATED + }, + UpdatedKeys.MASTER_KEY_ID + " = ?", + new String[]{"" + masterKeyId}, + null + ); + if (lastUpdatedCursor.moveToNext()) { + // there was an entry to re-insert + // this operation must happen after the new key is inserted + ContentValues lastUpdatedEntry = new ContentValues(2); + lastUpdatedEntry.put(UpdatedKeys.MASTER_KEY_ID, + lastUpdatedCursor.getLong(INDEX_MASTER_KEY_ID)); + lastUpdatedEntry.put(UpdatedKeys.LAST_UPDATED, + lastUpdatedCursor.getLong(INDEX_LAST_UPDATED)); + operations.add( + ContentProviderOperation + .newInsert(UpdatedKeys.CONTENT_URI) + .withValues(lastUpdatedEntry) + .build() + ); + } + lastUpdatedCursor.close(); + try { // delete old version of this keyRing, which also deletes all keys and userIds on cascade int deleted = mContentResolver.delete( @@ -725,7 +759,7 @@ public class ProviderHelper { LongSparseArray<WrappedSignature> trustedCerts = new LongSparseArray<>(); @Override - public int compareTo(UserPacketItem o) { + public int compareTo(@NonNull UserPacketItem o) { // revoked keys always come last! //noinspection DoubleNegation if ((selfRevocation != null) != (o.selfRevocation != null)) { @@ -782,7 +816,7 @@ public class ProviderHelper { // first, mark all keys as not available ContentValues values = new ContentValues(); - values.put(Keys.HAS_SECRET, SecretKeyType.UNAVAILABLE.getNum()); + values.put(Keys.HAS_SECRET, SecretKeyType.GNU_DUMMY.getNum()); mContentResolver.update(uri, values, null, null); // then, mark exactly the keys we have available @@ -831,7 +865,7 @@ public class ProviderHelper { mIndent -= 1; // this implicitly leaves all keys which were not in the secret key ring - // with has_secret = 0 + // with has_secret = 1 } log(LogType.MSG_IS_SUCCESS); @@ -906,7 +940,8 @@ public class ProviderHelper { // If there is a secret key, merge new data (if any) and save the key for later CanonicalizedSecretKeyRing canSecretRing; try { - UncachedKeyRing secretRing = getCanonicalizedSecretKeyRing(publicRing.getMasterKeyId()).getUncachedKeyRing(); + UncachedKeyRing secretRing = getCanonicalizedSecretKeyRing(publicRing.getMasterKeyId()) + .getUncachedKeyRing(); // Merge data from new public ring into secret one log(LogType.MSG_IP_MERGE_SECRET); @@ -1031,7 +1066,8 @@ public class ProviderHelper { publicRing = secretRing.extractPublicKeyRing(); } - CanonicalizedPublicKeyRing canPublicRing = (CanonicalizedPublicKeyRing) publicRing.canonicalize(mLog, mIndent); + CanonicalizedPublicKeyRing canPublicRing = (CanonicalizedPublicKeyRing) publicRing.canonicalize(mLog, + mIndent); if (canPublicRing == null) { return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } @@ -1057,6 +1093,7 @@ public class ProviderHelper { } + @NonNull public ConsolidateResult consolidateDatabaseStep1(Progressable progress) { OperationLog log = new OperationLog(); @@ -1082,7 +1119,7 @@ public class ProviderHelper { indent += 1; final Cursor cursor = mContentResolver.query(KeyRingData.buildSecretKeyRingUri(), - new String[]{ KeyRingData.KEY_RING_DATA }, null, null, null); + new String[]{KeyRingData.KEY_RING_DATA}, null, null, null); if (cursor == null) { log.add(LogType.MSG_CON_ERROR_DB, indent); @@ -1124,6 +1161,7 @@ public class ProviderHelper { } }); + cursor.close(); } catch (IOException e) { Log.e(Constants.TAG, "error saving secret", e); @@ -1143,7 +1181,7 @@ public class ProviderHelper { final Cursor cursor = mContentResolver.query( KeyRingData.buildPublicKeyRingUri(), - new String[]{ KeyRingData.KEY_RING_DATA }, null, null, null); + new String[]{KeyRingData.KEY_RING_DATA}, null, null, null); if (cursor == null) { log.add(LogType.MSG_CON_ERROR_DB, indent); @@ -1185,6 +1223,7 @@ public class ProviderHelper { } }); + cursor.close(); } catch (IOException e) { Log.e(Constants.TAG, "error saving public", e); @@ -1200,12 +1239,14 @@ public class ProviderHelper { return consolidateDatabaseStep2(log, indent, progress, false); } + @NonNull public ConsolidateResult consolidateDatabaseStep2(Progressable progress) { return consolidateDatabaseStep2(new OperationLog(), 0, progress, true); } private static boolean mConsolidateCritical = false; + @NonNull private ConsolidateResult consolidateDatabaseStep2( OperationLog log, int indent, Progressable progress, boolean recovery) { @@ -1231,6 +1272,28 @@ public class ProviderHelper { } // 2. wipe database (IT'S DANGEROUS) + + // first, backup our list of updated key times + ArrayList<ContentValues> updatedKeysValues = new ArrayList<>(); + final int INDEX_MASTER_KEY_ID = 0; + final int INDEX_LAST_UPDATED = 1; + Cursor lastUpdatedCursor = mContentResolver.query( + UpdatedKeys.CONTENT_URI, + new String[]{ + UpdatedKeys.MASTER_KEY_ID, + UpdatedKeys.LAST_UPDATED + }, + null, null, null); + while (lastUpdatedCursor.moveToNext()) { + ContentValues values = new ContentValues(); + values.put(UpdatedKeys.MASTER_KEY_ID, + lastUpdatedCursor.getLong(INDEX_MASTER_KEY_ID)); + values.put(UpdatedKeys.LAST_UPDATED, + lastUpdatedCursor.getLong(INDEX_LAST_UPDATED)); + updatedKeysValues.add(values); + } + lastUpdatedCursor.close(); + log.add(LogType.MSG_CON_DB_CLEAR, indent); mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); @@ -1248,9 +1311,9 @@ public class ProviderHelper { // 3. Re-Import secret keyrings from cache if (numSecrets > 0) { - ImportKeyResult result = new ImportExportOperation(mContext, this, + ImportKeyResult result = new ImportOperation(mContext, this, new ProgressFixedScaler(progress, 10, 25, 100, R.string.progress_con_reimport)) - .importKeyRings(itSecrets, numSecrets, null); + .serialKeyRingImport(itSecrets, numSecrets, null, null); log.add(result, indent); } else { log.add(LogType.MSG_CON_REIMPORT_SECRET_SKIP, indent); @@ -1276,10 +1339,14 @@ public class ProviderHelper { // 4. Re-Import public keyrings from cache if (numPublics > 0) { - ImportKeyResult result = new ImportExportOperation(mContext, this, + ImportKeyResult result = new ImportOperation(mContext, this, new ProgressFixedScaler(progress, 25, 99, 100, R.string.progress_con_reimport)) - .importKeyRings(itPublics, numPublics, null); + .serialKeyRingImport(itPublics, numPublics, null, null); log.add(result, indent); + // re-insert our backed up list of updated key times + // TODO: can this cause issues in case a public key re-import failed? + mContentResolver.bulkInsert(UpdatedKeys.CONTENT_URI, + updatedKeysValues.toArray(new ContentValues[updatedKeysValues.size()])); } else { log.add(LogType.MSG_CON_REIMPORT_PUBLIC_SKIP, indent); } @@ -1389,6 +1456,14 @@ public class ProviderHelper { return getKeyRingAsArmoredString(data); } + public Uri renewKeyLastUpdatedTime(long masterKeyId, long time, TimeUnit timeUnit) { + ContentValues values = new ContentValues(); + values.put(UpdatedKeys.MASTER_KEY_ID, masterKeyId); + values.put(UpdatedKeys.LAST_UPDATED, timeUnit.toSeconds(time)); + + return mContentResolver.insert(UpdatedKeys.CONTENT_URI, values); + } + public ArrayList<String> getRegisteredApiApps() { Cursor cursor = mContentResolver.query(ApiApps.CONTENT_URI, null, null, null, null); @@ -1414,7 +1489,7 @@ public class ProviderHelper { private ContentValues contentValueForApiApps(AppSettings appSettings) { ContentValues values = new ContentValues(); values.put(ApiApps.PACKAGE_NAME, appSettings.getPackageName()); - values.put(ApiApps.PACKAGE_CERTIFICATE, appSettings.getPackageSignature()); + values.put(ApiApps.PACKAGE_CERTIFICATE, appSettings.getPackageCertificate()); return values; } @@ -1426,9 +1501,9 @@ public class ProviderHelper { // DEPRECATED and thus hardcoded values.put(KeychainContract.ApiAccounts.COMPRESSION, CompressionAlgorithmTags.ZLIB); values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM, - PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT); values.put(KeychainContract.ApiAccounts.HASH_ALORITHM, - PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED); + PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT); return values; } @@ -1460,7 +1535,7 @@ public class ProviderHelper { settings = new AppSettings(); settings.setPackageName(cursor.getString( cursor.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME))); - settings.setPackageSignature(cursor.getBlob( + settings.setPackageCertificate(cursor.getBlob( cursor.getColumnIndex(KeychainContract.ApiApps.PACKAGE_CERTIFICATE))); } } finally { @@ -1514,8 +1589,8 @@ public class ProviderHelper { return keyIds; } - public Set<Long> getAllowedKeyIdsForApp(Uri uri) { - Set<Long> keyIds = new HashSet<>(); + public HashSet<Long> getAllowedKeyIdsForApp(Uri uri) { + HashSet<Long> keyIds = new HashSet<>(); Cursor cursor = mContentResolver.query(uri, null, null, null, null); try { |