From f13953e8fc8570a77d3652b9339dd66658c948c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 10 Mar 2015 11:34:35 +0100 Subject: API 7 --- .../keychain/provider/ProviderHelper.java | 108 +++++++++++---------- 1 file changed, 59 insertions(+), 49 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider') 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 6366e8536..6cd251be5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -28,6 +28,7 @@ import android.net.Uri; import android.os.RemoteException; import android.support.v4.util.LongSparseArray; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; @@ -43,6 +44,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.PgpHelper; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; @@ -81,15 +83,15 @@ import java.util.Iterator; import java.util.List; import java.util.Set; -/** This class contains high level methods for database access. Despite its +/** + * This class contains high level methods for database access. Despite its * name, it is not only a helper but actually the main interface for all * synchronous database operations. - * + *

* Operations in this class write logs. These can be obtained from the * OperationResultParcel return values directly, but are also accumulated over * the lifetime of the executing ProviderHelper object unless the resetLog() * method is called to start a new one specifically. - * */ public class ProviderHelper { private final Context mContext; @@ -126,12 +128,13 @@ public class ProviderHelper { } public void log(LogType type) { - if(mLog != null) { + if (mLog != null) { mLog.add(type, mIndent); } } + public void log(LogType type, Object... parameters) { - if(mLog != null) { + if (mLog != null) { mLog.add(type, mIndent, parameters); } } @@ -213,7 +216,7 @@ public class ProviderHelper { } private LongSparseArray getTrustedMasterKeys() { - Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[] { + Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ KeyRings.MASTER_KEY_ID, // we pick from cache only information that is not easily available from keyrings KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED, @@ -288,7 +291,7 @@ public class ProviderHelper { boolean hasAnySecret = cursor.getInt(0) > 0; int verified = cursor.getInt(1); byte[] blob = cursor.getBlob(2); - if(secret &! hasAnySecret) { + if (secret & !hasAnySecret) { throw new NotFoundException("Secret key not available!"); } return secret @@ -305,7 +308,7 @@ public class ProviderHelper { } // bits, in order: CESA. make SURE these are correct, we will get bad log entries otherwise!! - static final LogType LOG_TYPES_FLAG_MASTER[] = new LogType[] { + static final LogType LOG_TYPES_FLAG_MASTER[] = new LogType[]{ LogType.MSG_IP_MASTER_FLAGS_XXXX, LogType.MSG_IP_MASTER_FLAGS_CXXX, LogType.MSG_IP_MASTER_FLAGS_XEXX, LogType.MSG_IP_MASTER_FLAGS_CEXX, LogType.MSG_IP_MASTER_FLAGS_XXSX, LogType.MSG_IP_MASTER_FLAGS_CXSX, @@ -317,7 +320,7 @@ public class ProviderHelper { }; // same as above, but for subkeys - static final LogType LOG_TYPES_FLAG_SUBKEY[] = new LogType[] { + static final LogType LOG_TYPES_FLAG_SUBKEY[] = new LogType[]{ LogType.MSG_IP_SUBKEY_FLAGS_XXXX, LogType.MSG_IP_SUBKEY_FLAGS_CXXX, LogType.MSG_IP_SUBKEY_FLAGS_XEXX, LogType.MSG_IP_SUBKEY_FLAGS_CEXX, LogType.MSG_IP_SUBKEY_FLAGS_XXSX, LogType.MSG_IP_SUBKEY_FLAGS_CXSX, @@ -328,8 +331,9 @@ public class ProviderHelper { LogType.MSG_IP_SUBKEY_FLAGS_XESA, LogType.MSG_IP_SUBKEY_FLAGS_CESA }; - /** Saves an UncachedKeyRing of the public variant into the db. - * + /** + * Saves an UncachedKeyRing of the public variant into the db. + *

* This method will not delete all previous data for this masterKeyId from the database prior * to inserting. All public data is effectively re-inserted, secret keyrings are left deleted * and need to be saved externally to be preserved past the operation. @@ -403,7 +407,7 @@ public class ProviderHelper { if (key.getKeyUsage() == null) { log(LogType.MSG_IP_MASTER_FLAGS_UNSPECIFIED); } else { - log(LOG_TYPES_FLAG_MASTER[(c?1:0) + (e?2:0) + (s?4:0) + (a?8:0)]); + log(LOG_TYPES_FLAG_MASTER[(c ? 1 : 0) + (e ? 2 : 0) + (s ? 4 : 0) + (a ? 8 : 0)]); } } else { if (key.getKeyUsage() == null) { @@ -492,7 +496,7 @@ public class ProviderHelper { try { cert.init(trustedKey); // if it doesn't certify, leave a note and skip - if ( ! cert.verifySignature(masterKey, rawUserId)) { + if (!cert.verifySignature(masterKey, rawUserId)) { log(LogType.MSG_IP_UID_CERT_BAD); continue; } @@ -537,7 +541,7 @@ public class ProviderHelper { ArrayList userAttributes = masterKey.getUnorderedUserAttributes(); // Don't spam the log if there aren't even any attributes - if ( ! userAttributes.isEmpty()) { + if (!userAttributes.isEmpty()) { log(LogType.MSG_IP_UAT_CLASSIFYING); } @@ -592,7 +596,7 @@ public class ProviderHelper { try { cert.init(trustedKey); // if it doesn't certify, leave a note and skip - if ( ! cert.verifySignature(masterKey, userAttribute)) { + if (!cert.verifySignature(masterKey, userAttribute)) { log(LogType.MSG_IP_UAT_CERT_BAD); continue; } @@ -660,7 +664,7 @@ public class ProviderHelper { selfCertsAreTrusted ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF)); // iterate over signatures - for (int i = 0; i < item.trustedCerts.size() ; i++) { + for (int i = 0; i < item.trustedCerts.size(); i++) { WrappedSignature sig = item.trustedCerts.valueAt(i); // if it's a revocation if (sig.isRevocation()) { @@ -725,7 +729,7 @@ public class ProviderHelper { public int compareTo(UserPacketItem o) { // revoked keys always come last! //noinspection DoubleNegation - if ( (selfRevocation != null) != (o.selfRevocation != null)) { + if ((selfRevocation != null) != (o.selfRevocation != null)) { return selfRevocation != null ? 1 : -1; } // if one is a user id, but the other isn't, the user id always comes first. @@ -742,7 +746,8 @@ public class ProviderHelper { } } - /** Saves an UncachedKeyRing of the secret variant into the db. + /** + * Saves an UncachedKeyRing of the secret variant into the db. * This method will fail if no corresponding public keyring is in the database! */ private int saveCanonicalizedSecretKeyRing(CanonicalizedSecretKeyRing keyRing) { @@ -789,7 +794,7 @@ public class ProviderHelper { SecretKeyType mode = sub.getSecretKeyType(); values.put(Keys.HAS_SECRET, mode.getNum()); int upd = mContentResolver.update(uri, values, Keys.KEY_ID + " = ?", - new String[]{ Long.toString(id) }); + new String[]{Long.toString(id)}); if (upd == 1) { switch (mode) { case PASSPHRASE: @@ -843,8 +848,9 @@ public class ProviderHelper { return savePublicKeyRing(keyRing, new ProgressScaler()); } - /** Save a public keyring into the database. - * + /** + * Save a public keyring into the database. + *

* This is a high level method, which takes care of merging all new information into the old and * keep public and secret keyrings in sync. */ @@ -949,7 +955,7 @@ public class ProviderHelper { log(LogType.MSG_IS, KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); mIndent += 1; - if ( ! secretRing.isSecret()) { + if (!secretRing.isSecret()) { log(LogType.MSG_IS_BAD_TYPE_PUBLIC); return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null); } @@ -1420,9 +1426,13 @@ public class ProviderHelper { ContentValues values = new ContentValues(); values.put(KeychainContract.ApiAccounts.ACCOUNT_NAME, accSettings.getAccountName()); values.put(KeychainContract.ApiAccounts.KEY_ID, accSettings.getKeyId()); - values.put(KeychainContract.ApiAccounts.COMPRESSION, accSettings.getCompression()); - values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM, accSettings.getEncryptionAlgorithm()); - values.put(KeychainContract.ApiAccounts.HASH_ALORITHM, accSettings.getHashAlgorithm()); + + // DEPRECATED and thus hardcoded + values.put(KeychainContract.ApiAccounts.COMPRESSION, CompressionAlgorithmTags.ZLIB); + values.put(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM, + PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + values.put(KeychainContract.ApiAccounts.HASH_ALORITHM, + PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED); return values; } @@ -1478,12 +1488,6 @@ public class ProviderHelper { cursor.getColumnIndex(KeychainContract.ApiAccounts.ACCOUNT_NAME))); settings.setKeyId(cursor.getLong( cursor.getColumnIndex(KeychainContract.ApiAccounts.KEY_ID))); - settings.setCompression(cursor.getInt( - cursor.getColumnIndexOrThrow(KeychainContract.ApiAccounts.COMPRESSION))); - settings.setHashAlgorithm(cursor.getInt( - cursor.getColumnIndexOrThrow(KeychainContract.ApiAccounts.HASH_ALORITHM))); - settings.setEncryptionAlgorithm(cursor.getInt( - cursor.getColumnIndexOrThrow(KeychainContract.ApiAccounts.ENCRYPTION_ALGORITHM))); } } finally { if (cursor != null) { @@ -1547,26 +1551,32 @@ public class ProviderHelper { } } + public void addAllowedKeyIdForApp(Uri uri, long allowedKeyId) { + ContentValues values = new ContentValues(); + values.put(ApiAllowedKeys.KEY_ID, allowedKeyId); + mContentResolver.insert(uri, values); + } + public Set getAllFingerprints(Uri uri) { - Set fingerprints = new HashSet<>(); - String[] projection = new String[]{KeyRings.FINGERPRINT}; - Cursor cursor = mContentResolver.query(uri, projection, null, null, null); - try { - if(cursor != null) { - int fingerprintColumn = cursor.getColumnIndex(KeyRings.FINGERPRINT); - while(cursor.moveToNext()) { - fingerprints.add( + Set fingerprints = new HashSet<>(); + String[] projection = new String[]{KeyRings.FINGERPRINT}; + Cursor cursor = mContentResolver.query(uri, projection, null, null, null); + try { + if (cursor != null) { + int fingerprintColumn = cursor.getColumnIndex(KeyRings.FINGERPRINT); + while (cursor.moveToNext()) { + fingerprints.add( KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(fingerprintColumn)) - ); - } - } - } finally { - if (cursor != null) { - cursor.close(); - } - } - return fingerprints; - } + ); + } + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return fingerprints; + } public byte[] getApiAppSignature(String packageName) { Uri queryUri = ApiApps.buildByPackageNameUri(packageName); -- cgit v1.2.3 From 9ff4d7b2bc0830e96c7d844f2ffc7d5da798b646 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 11 Mar 2015 18:28:36 +0100 Subject: change user_id primary key in database, use keyring rather than unified query in consolidate --- .../keychain/provider/KeychainDatabase.java | 14 ++++++++++---- .../keychain/provider/ProviderHelper.java | 17 +++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index b88cd6006..4a162989f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -53,7 +53,7 @@ import java.io.IOException; */ public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "openkeychain.db"; - private static final int DATABASE_VERSION = 8; + private static final int DATABASE_VERSION = 9; static Boolean apgHack = false; private Context mContext; @@ -61,7 +61,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { String KEY_RINGS_PUBLIC = "keyrings_public"; String KEY_RINGS_SECRET = "keyrings_secret"; String KEYS = "keys"; - String USER_PACKETS = "user_ids"; + String USER_PACKETS = "user_packets"; String CERTS = "certs"; String API_APPS = "api_apps"; String API_ACCOUNTS = "api_accounts"; @@ -119,8 +119,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { + UserPacketsColumns.IS_REVOKED + " INTEGER, " + UserPacketsColumns.RANK+ " INTEGER, " - + "PRIMARY KEY(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.USER_ID + "), " - + "UNIQUE (" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + "), " + + "PRIMARY KEY(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + "), " + "FOREIGN KEY(" + UserPacketsColumns.MASTER_KEY_ID + ") REFERENCES " + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + ")"; @@ -267,6 +266,13 @@ public class KeychainDatabase extends SQLiteOpenHelper { } catch (Exception e) { // never mind, the column probably already existed } + case 9: + // tbale name for user_ids changed to user_packets + db.execSQL("DROP TABLE IF EXISTS certs"); + db.execSQL("DROP TABLE IF EXISTS user_ids"); + db.execSQL(CREATE_USER_PACKETS); + db.execSQL(CREATE_CERTS); + } // always do consolidate after upgrade 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 6cd251be5..1d3934620 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1082,9 +1082,8 @@ public class ProviderHelper { log.add(LogType.MSG_CON_SAVE_SECRET, indent); indent += 1; - final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ - KeyRings.PRIVKEY_DATA, KeyRings.FINGERPRINT, KeyRings.HAS_ANY_SECRET - }, KeyRings.HAS_ANY_SECRET + " = 1", null, null); + final Cursor cursor = mContentResolver.query(KeyRingData.buildSecretKeyRingUri(), + new String[]{ KeyRingData.KEY_RING_DATA }, null, null, null); if (cursor == null) { log.add(LogType.MSG_CON_ERROR_DB, indent); @@ -1106,8 +1105,7 @@ public class ProviderHelper { if (cursor.isAfterLast()) { return false; } - ring = new ParcelableKeyRing(KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(1)), cursor.getBlob(0) - ); + ring = new ParcelableKeyRing(cursor.getBlob(0)); cursor.moveToNext(); return true; } @@ -1144,9 +1142,9 @@ public class ProviderHelper { log.add(LogType.MSG_CON_SAVE_PUBLIC, indent); indent += 1; - final Cursor cursor = mContentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[]{ - KeyRings.PUBKEY_DATA, KeyRings.FINGERPRINT - }, null, null, null); + final Cursor cursor = mContentResolver.query( + KeyRingData.buildPublicKeyRingUri(), + new String[]{ KeyRingData.KEY_RING_DATA }, null, null, null); if (cursor == null) { log.add(LogType.MSG_CON_ERROR_DB, indent); @@ -1168,8 +1166,7 @@ public class ProviderHelper { if (cursor.isAfterLast()) { return false; } - ring = new ParcelableKeyRing(KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(1)), cursor.getBlob(0) - ); + ring = new ParcelableKeyRing(cursor.getBlob(0)); cursor.moveToNext(); return true; } -- cgit v1.2.3 From c2593f29fffe858074f23512e5f4d6859c816bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 15 Mar 2015 02:40:31 +0100 Subject: Query for duplicate user ids --- .../sufficientlysecure/keychain/provider/KeychainContract.java | 1 + .../sufficientlysecure/keychain/provider/KeychainProvider.java | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 5856589c4..6af5f4217 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -123,6 +123,7 @@ public class KeychainContract { public static final String HAS_SIGN = "has_sign"; public static final String HAS_CERTIFY = "has_certify"; public static final String HAS_AUTHENTICATE = "has_authenticate"; + public static final String HAS_DUPLICATE_USER_ID = "has_duplicate_user_id"; public static final String PUBKEY_DATA = "pubkey_data"; public static final String PRIVKEY_DATA = "privkey_data"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 4ccfc3cd9..1351e0cbc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -273,7 +273,15 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.EXPIRY, Tables.KEYS + "." + Keys.EXPIRY); projectionMap.put(KeyRings.ALGORITHM, Tables.KEYS + "." + Keys.ALGORITHM); projectionMap.put(KeyRings.FINGERPRINT, Tables.KEYS + "." + Keys.FINGERPRINT); - projectionMap.put(KeyRings.USER_ID, UserPackets.USER_ID); + projectionMap.put(KeyRings.USER_ID, Tables.USER_PACKETS + "." + UserPackets.USER_ID); + projectionMap.put(KeyRings.HAS_DUPLICATE_USER_ID, + "(SELECT COUNT (*) FROM " + Tables.USER_PACKETS + " AS dups" + + " WHERE dups." + UserPackets.MASTER_KEY_ID + + " != " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND dups." + UserPackets.RANK + " = 0" + + " AND dups." + UserPackets.USER_ID + + " = "+ Tables.USER_PACKETS + "." + UserPackets.USER_ID + + ") AS " + KeyRings.HAS_DUPLICATE_USER_ID); projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED); projectionMap.put(KeyRings.PUBKEY_DATA, Tables.KEY_RINGS_PUBLIC + "." + KeyRingData.KEY_RING_DATA -- cgit v1.2.3