From 2b1c5358b77c88340639ae296dac01fdbf72295d Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 13 Jan 2015 23:09:48 +0100 Subject: make user_ids table typed, with attribute_data support Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java --- .../keychain/provider/KeychainContract.java | 10 ++- .../keychain/provider/KeychainDatabase.java | 35 ++++---- .../keychain/provider/KeychainProvider.java | 92 ++++++++++++++-------- .../keychain/provider/ProviderHelper.java | 19 +++-- 4 files changed, 94 insertions(+), 62 deletions(-) (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 2c02e429d..f4e00c36c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -51,9 +51,11 @@ public class KeychainContract { String EXPIRY = "expiry"; } - interface UserIdsColumns { + interface UserPacketsColumns { String MASTER_KEY_ID = "master_key_id"; // foreign key to key_rings._ID + String TYPE = "type"; // not a database id String USER_ID = "user_id"; // not a database id + String ATTRIBUTE_DATA = "attribute_data"; // not a database id String RANK = "rank"; // ONLY used for sorting! no key, no nothing! String IS_PRIMARY = "is_primary"; String IS_REVOKED = "is_revoked"; @@ -105,7 +107,7 @@ public class KeychainContract { public static final String BASE_API_APPS = "api_apps"; public static final String PATH_ACCOUNTS = "accounts"; - public static class KeyRings implements BaseColumns, KeysColumns, UserIdsColumns { + public static class KeyRings implements BaseColumns, KeysColumns, UserPacketsColumns { public static final String MASTER_KEY_ID = KeysColumns.MASTER_KEY_ID; public static final String IS_REVOKED = KeysColumns.IS_REVOKED; public static final String VERIFIED = CertsColumns.VERIFIED; @@ -225,7 +227,7 @@ public class KeychainContract { } - public static class UserIds implements UserIdsColumns, BaseColumns { + public static class UserPackets implements UserPacketsColumns, BaseColumns { public static final String VERIFIED = "verified"; public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); @@ -304,7 +306,7 @@ public class KeychainContract { } public static class Certs implements CertsColumns, BaseColumns { - public static final String USER_ID = UserIdsColumns.USER_ID; + public static final String USER_ID = UserPacketsColumns.USER_ID; public static final String SIGNER_UID = "signer_user_id"; public static final int UNVERIFIED = 0; 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 84a50dc65..5ce5eec17 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -33,7 +33,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns; import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity; import org.sufficientlysecure.keychain.util.Log; @@ -52,7 +52,7 @@ import java.io.IOException; */ public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "openkeychain.db"; - private static final int DATABASE_VERSION = 6; + private static final int DATABASE_VERSION = 7; static Boolean apgHack = false; private Context mContext; @@ -60,7 +60,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { String KEY_RINGS_PUBLIC = "keyrings_public"; String KEY_RINGS_SECRET = "keyrings_secret"; String KEYS = "keys"; - String USER_IDS = "user_ids"; + String USER_PACKETS = "user_ids"; String CERTS = "certs"; String API_APPS = "api_apps"; String API_ACCOUNTS = "api_accounts"; @@ -106,18 +106,20 @@ public class KeychainDatabase extends SQLiteOpenHelper { + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + ")"; - private static final String CREATE_USER_IDS = - "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS + "(" - + UserIdsColumns.MASTER_KEY_ID + " INTEGER, " - + UserIdsColumns.USER_ID + " TEXT, " + private static final String CREATE_USER_PACKETS = + "CREATE TABLE IF NOT EXISTS " + Tables.USER_PACKETS + "(" + + UserPacketsColumns.MASTER_KEY_ID + " INTEGER, " + + UserPacketsColumns.TYPE + " INT, " + + UserPacketsColumns.USER_ID + " TEXT, " + + UserPacketsColumns.ATTRIBUTE_DATA + " BLOB, " - + UserIdsColumns.IS_PRIMARY + " INTEGER, " - + UserIdsColumns.IS_REVOKED + " INTEGER, " - + UserIdsColumns.RANK+ " INTEGER, " + + UserPacketsColumns.IS_PRIMARY + " INTEGER, " + + UserPacketsColumns.IS_REVOKED + " INTEGER, " + + UserPacketsColumns.RANK+ " INTEGER, " - + "PRIMARY KEY(" + UserIdsColumns.MASTER_KEY_ID + ", " + UserIdsColumns.USER_ID + "), " - + "UNIQUE (" + UserIdsColumns.MASTER_KEY_ID + ", " + UserIdsColumns.RANK + "), " - + "FOREIGN KEY(" + UserIdsColumns.MASTER_KEY_ID + ") REFERENCES " + + "PRIMARY KEY(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.USER_ID + "), " + + "UNIQUE (" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + "), " + + "FOREIGN KEY(" + UserPacketsColumns.MASTER_KEY_ID + ") REFERENCES " + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + ")"; @@ -138,7 +140,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { + "FOREIGN KEY(" + CertsColumns.MASTER_KEY_ID + ") REFERENCES " + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE," + "FOREIGN KEY(" + CertsColumns.MASTER_KEY_ID + ", " + CertsColumns.RANK + ") REFERENCES " - + Tables.USER_IDS + "(" + UserIdsColumns.MASTER_KEY_ID + ", " + UserIdsColumns.RANK + ") ON DELETE CASCADE" + + Tables.USER_PACKETS + "(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + ") ON DELETE CASCADE" + ")"; private static final String CREATE_API_APPS = @@ -189,7 +191,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { db.execSQL(CREATE_KEYRINGS_PUBLIC); db.execSQL(CREATE_KEYRINGS_SECRET); db.execSQL(CREATE_KEYS); - db.execSQL(CREATE_USER_IDS); + db.execSQL(CREATE_USER_PACKETS); db.execSQL(CREATE_CERTS); db.execSQL(CREATE_API_APPS); db.execSQL(CREATE_API_APPS_ACCOUNTS); @@ -238,6 +240,9 @@ public class KeychainDatabase extends SQLiteOpenHelper { case 5: // do consolidate for 3.0 beta3 // fall through + case 6: + db.execSQL("ALTER TABLE user_ids ADD COLUMN type INTEGER"); + db.execSQL("ALTER TABLE user_ids ADD COLUMN attribute_data BLOB"); } // always do consolidate after upgrade 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 d40287690..13a923f03 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -37,7 +37,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.UserIds; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.util.Log; @@ -205,7 +206,7 @@ public class KeychainProvider extends ContentProvider { return Keys.CONTENT_TYPE; case KEY_RING_USER_IDS: - return UserIds.CONTENT_TYPE; + return UserPackets.CONTENT_TYPE; case KEY_RING_SECRET: return KeyRings.CONTENT_ITEM_TYPE; @@ -262,7 +263,7 @@ 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, UserIds.USER_ID); + projectionMap.put(KeyRings.USER_ID, UserPackets.USER_ID); projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED); projectionMap.put(KeyRings.PUBKEY_DATA, Tables.KEY_RINGS_PUBLIC + "." + KeyRingData.KEY_RING_DATA @@ -296,11 +297,12 @@ public class KeychainProvider extends ContentProvider { qb.setTables( Tables.KEYS - + " INNER JOIN " + Tables.USER_IDS + " ON (" + + " INNER JOIN " + Tables.USER_PACKETS + " ON (" + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = " - + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID - + " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = 0" + + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + // we KNOW that the rank zero user packet is a user id! + + " AND " + Tables.USER_PACKETS + "." + UserPackets.RANK + " = 0" + ") LEFT JOIN " + Tables.CERTS + " ON (" + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = " @@ -376,7 +378,7 @@ public class KeychainProvider extends ContentProvider { String subkey = Long.valueOf(uri.getLastPathSegment()).toString(); qb.appendWhere(" AND EXISTS (" + " SELECT 1 FROM " + Tables.KEYS + " AS tmp" - + " WHERE tmp." + UserIds.MASTER_KEY_ID + + " WHERE tmp." + UserPackets.MASTER_KEY_ID + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " AND tmp." + Keys.KEY_ID + " = " + subkey + "" + ")"); @@ -398,15 +400,15 @@ public class KeychainProvider extends ContentProvider { if (i != 0) { emailWhere += " OR "; } - emailWhere += "tmp." + UserIds.USER_ID + " LIKE "; + emailWhere += "tmp." + UserPackets.USER_ID + " LIKE "; // match '*', so it has to be at the *end* of the user id emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">"); gotCondition = true; } if(gotCondition) { qb.appendWhere(" AND EXISTS (" - + " SELECT 1 FROM " + Tables.USER_IDS + " AS tmp" - + " WHERE tmp." + UserIds.MASTER_KEY_ID + + " SELECT 1 FROM " + Tables.USER_PACKETS + " AS tmp" + + " WHERE tmp." + UserPackets.MASTER_KEY_ID + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " AND (" + emailWhere + ")" + ")"); @@ -420,7 +422,7 @@ public class KeychainProvider extends ContentProvider { } if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIds.USER_ID + " ASC"; + sortOrder = Tables.USER_PACKETS + "." + UserPackets.USER_ID + " ASC"; } // uri to watch is all /key_rings/ @@ -459,36 +461,42 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_USER_IDS: case KEY_RING_USER_IDS: { HashMap projectionMap = new HashMap(); - projectionMap.put(UserIds._ID, Tables.USER_IDS + ".oid AS _id"); - projectionMap.put(UserIds.MASTER_KEY_ID, Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID); - projectionMap.put(UserIds.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID); - projectionMap.put(UserIds.RANK, Tables.USER_IDS + "." + UserIds.RANK); - projectionMap.put(UserIds.IS_PRIMARY, Tables.USER_IDS + "." + UserIds.IS_PRIMARY); - projectionMap.put(UserIds.IS_REVOKED, Tables.USER_IDS + "." + UserIds.IS_REVOKED); + projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id"); + projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID); + projectionMap.put(UserPackets.TYPE, Tables.USER_PACKETS + "." + UserPackets.TYPE); + projectionMap.put(UserPackets.USER_ID, Tables.USER_PACKETS + "." + UserPackets.USER_ID); + projectionMap.put(UserPackets.ATTRIBUTE_DATA, Tables.USER_PACKETS + "." + UserPackets.ATTRIBUTE_DATA); + projectionMap.put(UserPackets.RANK, Tables.USER_PACKETS + "." + UserPackets.RANK); + projectionMap.put(UserPackets.IS_PRIMARY, Tables.USER_PACKETS + "." + UserPackets.IS_PRIMARY); + projectionMap.put(UserPackets.IS_REVOKED, Tables.USER_PACKETS + "." + UserPackets.IS_REVOKED); // we take the minimum (>0) here, where "1" is "verified by known secret key" - projectionMap.put(UserIds.VERIFIED, "MIN(" + Certs.VERIFIED + ") AS " + UserIds.VERIFIED); + projectionMap.put(UserPackets.VERIFIED, "MIN(" + Certs.VERIFIED + ") AS " + UserPackets.VERIFIED); qb.setProjectionMap(projectionMap); - qb.setTables(Tables.USER_IDS + qb.setTables(Tables.USER_PACKETS + " LEFT JOIN " + Tables.CERTS + " ON (" - + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " = " + + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = " + Tables.CERTS + "." + Certs.MASTER_KEY_ID - + " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = " + + " AND " + Tables.USER_PACKETS + "." + UserPackets.RANK + " = " + Tables.CERTS + "." + Certs.RANK + " AND " + Tables.CERTS + "." + Certs.VERIFIED + " > 0" + ")"); - groupBy = Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID - + ", " + Tables.USER_IDS + "." + UserIds.RANK; + groupBy = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + + ", " + Tables.USER_PACKETS + "." + UserPackets.RANK; + + // for now, we only respect user ids here, so TYPE must be NULL + // TODO expand with KEY_RING_USER_PACKETS query type which lifts this restriction + qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL AND "); // If we are searching for a particular keyring's ids, add where if (match == KEY_RING_USER_IDS) { - qb.appendWhere(Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " = "); + qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = "); qb.appendWhereEscapeString(uri.getPathSegments().get(1)); } if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " ASC" - + "," + Tables.USER_IDS + "." + UserIds.RANK + " ASC"; + sortOrder = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " ASC" + + "," + Tables.USER_PACKETS + "." + UserPackets.RANK + " ASC"; } break; @@ -542,20 +550,24 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(Certs.CREATION, Tables.CERTS + "." + Certs.CREATION); projectionMap.put(Certs.KEY_ID_CERTIFIER, Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER); projectionMap.put(Certs.DATA, Tables.CERTS + "." + Certs.DATA); - projectionMap.put(Certs.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID); - projectionMap.put(Certs.SIGNER_UID, "signer." + UserIds.USER_ID + " AS " + Certs.SIGNER_UID); + projectionMap.put(Certs.USER_ID, Tables.USER_PACKETS + "." + UserPackets.USER_ID); + projectionMap.put(Certs.SIGNER_UID, "signer." + UserPackets.USER_ID + " AS " + Certs.SIGNER_UID); qb.setProjectionMap(projectionMap); qb.setTables(Tables.CERTS - + " JOIN " + Tables.USER_IDS + " ON (" + + " JOIN " + Tables.USER_PACKETS + " ON (" + Tables.CERTS + "." + Certs.MASTER_KEY_ID + " = " - + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " AND " + Tables.CERTS + "." + Certs.RANK + " = " - + Tables.USER_IDS + "." + UserIds.RANK - + ") LEFT JOIN " + Tables.USER_IDS + " AS signer ON (" + + Tables.USER_PACKETS + "." + UserPackets.RANK + // for now, we only return user ids here, so TYPE must be NULL + // TODO at some point, we should lift this restriction + + " AND " + + Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL" + + ") LEFT JOIN " + Tables.USER_PACKETS + " AS signer ON (" + Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER + " = " - + "signer." + UserIds.MASTER_KEY_ID + + "signer." + UserPackets.MASTER_KEY_ID + " AND " + "signer." + Keys.RANK + " = 0" + ")"); @@ -662,8 +674,18 @@ public class KeychainProvider extends ContentProvider { break; case KEY_RING_USER_IDS: - db.insertOrThrow(Tables.USER_IDS, null, values); - keyId = values.getAsLong(UserIds.MASTER_KEY_ID); + // iff TYPE is null, user_id MUST be null as well + if ( ! (values.get(UserPacketsColumns.TYPE) == null + ? (values.get(UserPacketsColumns.USER_ID) != null && values.get(UserPacketsColumns.ATTRIBUTE_DATA) == null) + : (values.get(UserPacketsColumns.ATTRIBUTE_DATA) != null && values.get(UserPacketsColumns.USER_ID) == null) + )) { + throw new AssertionError("Incorrect type for user packet! This is a bug!"); + } + if (values.get(UserPacketsColumns.RANK) == 0 && values.get(UserPacketsColumns.USER_ID) == null) { + throw new AssertionError("Rank 0 user packet must be a user id!"); + } + db.insertOrThrow(Tables.USER_PACKETS, null, values); + keyId = values.getAsLong(UserPackets.MASTER_KEY_ID); break; case KEY_RING_CERTS: 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 4f1b4b6c1..b3f98117d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -31,6 +31,7 @@ import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; import org.sufficientlysecure.keychain.util.Preferences; @@ -53,7 +54,6 @@ 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.UserIds; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; @@ -1236,13 +1236,16 @@ public class ProviderHelper { private ContentProviderOperation buildUserIdOperations(long masterKeyId, UserIdItem item, int rank) { ContentValues values = new ContentValues(); - values.put(UserIds.MASTER_KEY_ID, masterKeyId); - values.put(UserIds.USER_ID, item.userId); - values.put(UserIds.IS_PRIMARY, item.isPrimary); - values.put(UserIds.IS_REVOKED, item.isRevoked); - values.put(UserIds.RANK, rank); - - Uri uri = UserIds.buildUserIdsUri(masterKeyId); + values.put(UserPackets.MASTER_KEY_ID, masterKeyId); + values.put(UserPackets.USER_ID, item.userId); + values.put(UserPackets.IS_PRIMARY, item.isPrimary); + values.put(UserPackets.IS_REVOKED, item.isRevoked); + values.put(UserPackets.RANK, rank); + // we explicitly set these to null here, to indicate that this is a user id, not an attribute + values.put(UserPackets.TYPE, (String) null); + values.put(UserPackets.ATTRIBUTE_DATA, (String) null); + + Uri uri = UserPackets.buildUserIdsUri(masterKeyId); return ContentProviderOperation.newInsert(uri).withValues(values).build(); } -- cgit v1.2.3 From c57355b24a33200b1d6c35bfcac92d4c5bdfa908 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 14 Jan 2015 00:00:04 +0100 Subject: actually import user attributes (though they are not shown anywhere yet) --- .../keychain/provider/KeychainProvider.java | 4 +- .../keychain/provider/ProviderHelper.java | 129 +++++++++++++++++++-- 2 files changed, 121 insertions(+), 12 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider') 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 13a923f03..29b9c5f9f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -486,10 +486,12 @@ public class KeychainProvider extends ContentProvider { // for now, we only respect user ids here, so TYPE must be NULL // TODO expand with KEY_RING_USER_PACKETS query type which lifts this restriction - qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL AND "); + qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL"); // If we are searching for a particular keyring's ids, add where if (match == KEY_RING_USER_IDS) { + // TODO remove with the thing above + qb.appendWhere(" AND "); qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = "); qb.appendWhereEscapeString(uri.getPathSegments().get(1)); } 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 b3f98117d..c3990229d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -31,6 +31,7 @@ import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; @@ -439,18 +440,18 @@ public class ProviderHelper { // classify and order user ids. primary are moved to the front, revoked to the back, // otherwise the order in the keyfile is preserved. + List uids = new ArrayList(); + if (trustedKeys.size() == 0) { log(LogType.MSG_IP_UID_CLASSIFYING_ZERO); } else { log(LogType.MSG_IP_UID_CLASSIFYING, trustedKeys.size()); } mIndent += 1; - List uids = new ArrayList(); - for (byte[] rawUserId : new IterableIterator( - masterKey.getUnorderedRawUserIds().iterator())) { + for (byte[] rawUserId : masterKey.getUnorderedRawUserIds()) { String userId = Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId); - UserIdItem item = new UserIdItem(); + UserPacketItem item = new UserPacketItem(); uids.add(item); item.userId = userId; @@ -533,6 +534,105 @@ public class ProviderHelper { } mIndent -= 1; + ArrayList userAttributes = masterKey.getUnorderedUserAttributes(); + // Don't spam the log if there aren't even any attributes + if ( ! userAttributes.isEmpty()) { + log(LogType.MSG_IP_UAT_CLASSIFYING); + } + + mIndent += 1; + for (WrappedUserAttribute userAttribute : userAttributes) { + + UserPacketItem item = new UserPacketItem(); + uids.add(item); + item.type = userAttribute.getType(); + item.attributeData = userAttribute.getEncoded(); + + int unknownCerts = 0; + + switch (item.type) { + case WrappedUserAttribute.UAT_IMAGE: + log(LogType.MSG_IP_UAT_PROCESSING_IMAGE); + break; + default: + log(LogType.MSG_IP_UAT_PROCESSING_UNKNOWN); + break; + } + mIndent += 1; + // look through signatures for this specific key + for (WrappedSignature cert : new IterableIterator( + masterKey.getSignaturesForUserAttribute(userAttribute))) { + long certId = cert.getKeyId(); + // self signature + if (certId == masterKeyId) { + + // NOTE self-certificates are already verified during canonicalization, + // AND we know there is at most one cert plus at most one revocation + if (!cert.isRevocation()) { + item.selfCert = cert; + } else { + item.isRevoked = true; + log(LogType.MSG_IP_UAT_REVOKED); + } + continue; + + } + + // do we have a trusted key for this? + if (trustedKeys.indexOfKey(certId) < 0) { + unknownCerts += 1; + continue; + } + + // verify signatures from known private keys + CanonicalizedPublicKey trustedKey = trustedKeys.get(certId); + + try { + cert.init(trustedKey); + // if it doesn't certify, leave a note and skip + if ( ! cert.verifySignature(masterKey, userAttribute)) { + log(LogType.MSG_IP_UAT_CERT_BAD); + continue; + } + + log(cert.isRevocation() + ? LogType.MSG_IP_UAT_CERT_GOOD_REVOKE + : LogType.MSG_IP_UAT_CERT_GOOD, + KeyFormattingUtils.convertKeyIdToHexShort(trustedKey.getKeyId()) + ); + + // check if there is a previous certificate + WrappedSignature prev = item.trustedCerts.get(cert.getKeyId()); + if (prev != null) { + // if it's newer, skip this one + if (prev.getCreationTime().after(cert.getCreationTime())) { + log(LogType.MSG_IP_UAT_CERT_OLD); + continue; + } + // if the previous one was a non-revokable certification, no need to look further + if (!prev.isRevocation() && !prev.isRevokable()) { + log(LogType.MSG_IP_UAT_CERT_NONREVOKE); + continue; + } + log(LogType.MSG_IP_UAT_CERT_NEW); + } + item.trustedCerts.put(cert.getKeyId(), cert); + + } catch (PgpGeneralException e) { + log(LogType.MSG_IP_UAT_CERT_ERROR, + KeyFormattingUtils.convertKeyIdToHex(cert.getKeyId())); + } + + } + + if (unknownCerts > 0) { + log(LogType.MSG_IP_UAT_CERTS_UNKNOWN, unknownCerts); + } + mIndent -= 1; + + } + mIndent -= 1; + progress.setProgress(LogType.MSG_IP_UID_REORDER.getMsgId(), 65, 100); log(LogType.MSG_IP_UID_REORDER); // primary before regular before revoked (see UserIdItem.compareTo) @@ -540,7 +640,7 @@ public class ProviderHelper { Collections.sort(uids); // iterate and put into db for (int userIdRank = 0; userIdRank < uids.size(); userIdRank++) { - UserIdItem item = uids.get(userIdRank); + UserPacketItem item = uids.get(userIdRank); operations.add(buildUserIdOperations(masterKeyId, item, userIdRank)); if (item.selfCert != null) { // TODO get rid of "self verified" status? this cannot even happen anymore! @@ -605,15 +705,23 @@ public class ProviderHelper { } - private static class UserIdItem implements Comparable { + private static class UserPacketItem implements Comparable { + Integer type; String userId; + byte[] attributeData; boolean isPrimary = false; boolean isRevoked = false; WrappedSignature selfCert; LongSparseArray trustedCerts = new LongSparseArray(); @Override - public int compareTo(UserIdItem o) { + public int compareTo(UserPacketItem o) { + // if one is a user id, but the other isn't, the user id always comes first. + // we compare for null values here, so != is the correct operator! + // noinspection NumberEquality + if (type != o.type) { + return type == null ? -1 : 1; + } // if one key is primary but the other isn't, the primary one always comes first if (isPrimary != o.isPrimary) { return isPrimary ? -1 : 1; @@ -1234,16 +1342,15 @@ public class ProviderHelper { * Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing */ private ContentProviderOperation - buildUserIdOperations(long masterKeyId, UserIdItem item, int rank) { + buildUserIdOperations(long masterKeyId, UserPacketItem item, int rank) { ContentValues values = new ContentValues(); values.put(UserPackets.MASTER_KEY_ID, masterKeyId); + values.put(UserPackets.TYPE, item.type); values.put(UserPackets.USER_ID, item.userId); + values.put(UserPackets.ATTRIBUTE_DATA, item.attributeData); values.put(UserPackets.IS_PRIMARY, item.isPrimary); values.put(UserPackets.IS_REVOKED, item.isRevoked); values.put(UserPackets.RANK, rank); - // we explicitly set these to null here, to indicate that this is a user id, not an attribute - values.put(UserPackets.TYPE, (String) null); - values.put(UserPackets.ATTRIBUTE_DATA, (String) null); Uri uri = UserPackets.buildUserIdsUri(masterKeyId); -- cgit v1.2.3 From e71bd3d9dd80d7f9721192238b9f30093c1c6bfc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 19 Jan 2015 17:29:33 +0100 Subject: always show revoked user ids last! --- .../org/sufficientlysecure/keychain/provider/ProviderHelper.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 c3990229d..b2af5a0a0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -716,6 +716,10 @@ public class ProviderHelper { @Override public int compareTo(UserPacketItem o) { + // revoked keys always come last! + if (isRevoked != o.isRevoked) { + return isRevoked ? 1 : -1; + } // if one is a user id, but the other isn't, the user id always comes first. // we compare for null values here, so != is the correct operator! // noinspection NumberEquality @@ -726,10 +730,6 @@ public class ProviderHelper { if (isPrimary != o.isPrimary) { return isPrimary ? -1 : 1; } - // revoked keys always come last! - if (isRevoked != o.isRevoked) { - return isRevoked ? 1 : -1; - } return 0; } } -- cgit v1.2.3 From 8d9c3c05341a5cd4f1879df692453d1327ea6a96 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 25 Jan 2015 12:36:00 +0100 Subject: lift language level to java 7, and some code cleanup --- .../keychain/provider/KeychainProvider.java | 12 +++++----- .../keychain/provider/ProviderHelper.java | 28 +++++++++++----------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider') 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 29b9c5f9f..72475472e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -248,7 +248,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_UNIFIED: case KEY_RINGS_FIND_BY_EMAIL: case KEY_RINGS_FIND_BY_SUBKEY: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id"); projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); projectionMap.put(KeyRings.KEY_ID, Tables.KEYS + "." + Keys.KEY_ID); @@ -432,7 +432,7 @@ public class KeychainProvider extends ContentProvider { } case KEY_RING_KEYS: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(Keys._ID, Tables.KEYS + ".oid AS _id"); projectionMap.put(Keys.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); projectionMap.put(Keys.RANK, Tables.KEYS + "." + Keys.RANK); @@ -460,7 +460,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_USER_IDS: case KEY_RING_USER_IDS: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id"); projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID); projectionMap.put(UserPackets.TYPE, Tables.USER_PACKETS + "." + UserPackets.TYPE); @@ -507,7 +507,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_PUBLIC: case KEY_RING_PUBLIC: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_PUBLIC + ".oid AS _id"); projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID); projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA); @@ -525,7 +525,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_SECRET: case KEY_RING_SECRET: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_SECRET + ".oid AS _id"); projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID); projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA); @@ -543,7 +543,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RING_CERTS: case KEY_RING_CERTS_SPECIFIC: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(Certs._ID, Tables.CERTS + ".oid AS " + Certs._ID); projectionMap.put(Certs.MASTER_KEY_ID, Tables.CERTS + "." + Certs.MASTER_KEY_ID); projectionMap.put(Certs.RANK, Tables.CERTS + "." + Certs.RANK); 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 b2af5a0a0..a229f454f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -170,7 +170,7 @@ public class ProviderHelper { Cursor cursor = mContentResolver.query(uri, proj, selection, null, null); try { - HashMap result = new HashMap(proj.length); + HashMap result = new HashMap<>(proj.length); if (cursor != null && cursor.moveToFirst()) { int pos = 0; for (String p : proj) { @@ -221,7 +221,7 @@ public class ProviderHelper { }, KeyRings.HAS_ANY_SECRET + " = 1", null, null); try { - LongSparseArray result = new LongSparseArray(); + LongSparseArray result = new LongSparseArray<>(); if (cursor != null && cursor.moveToFirst()) do { long masterKeyId = cursor.getLong(0); @@ -350,7 +350,7 @@ public class ProviderHelper { mIndent += 1; // save all keys and userIds included in keyRing object in database - operations = new ArrayList(); + operations = new ArrayList<>(); log(LogType.MSG_IP_INSERT_KEYRING); { // insert keyring @@ -440,7 +440,7 @@ public class ProviderHelper { // classify and order user ids. primary are moved to the front, revoked to the back, // otherwise the order in the keyfile is preserved. - List uids = new ArrayList(); + List uids = new ArrayList<>(); if (trustedKeys.size() == 0) { log(LogType.MSG_IP_UID_CLASSIFYING_ZERO); @@ -460,7 +460,7 @@ public class ProviderHelper { log(LogType.MSG_IP_UID_PROCESSING, userId); mIndent += 1; // look through signatures for this specific key - for (WrappedSignature cert : new IterableIterator( + for (WrappedSignature cert : new IterableIterator<>( masterKey.getSignaturesForRawId(rawUserId))) { long certId = cert.getKeyId(); // self signature @@ -560,7 +560,7 @@ public class ProviderHelper { } mIndent += 1; // look through signatures for this specific key - for (WrappedSignature cert : new IterableIterator( + for (WrappedSignature cert : new IterableIterator<>( masterKey.getSignaturesForUserAttribute(userAttribute))) { long certId = cert.getKeyId(); // self signature @@ -712,7 +712,7 @@ public class ProviderHelper { boolean isPrimary = false; boolean isRevoked = false; WrappedSignature selfCert; - LongSparseArray trustedCerts = new LongSparseArray(); + LongSparseArray trustedCerts = new LongSparseArray<>(); @Override public int compareTo(UserPacketItem o) { @@ -1075,7 +1075,7 @@ public class ProviderHelper { // No keys existing might be a legitimate option, we write an empty file in that case cursor.moveToFirst(); ParcelableFileCache cache = - new ParcelableFileCache(mContext, "consolidate_secret.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_secret.pcl"); cache.writeCache(cursor.getCount(), new Iterator() { ParcelableKeyRing ring; @@ -1137,7 +1137,7 @@ public class ProviderHelper { // No keys existing might be a legitimate option, we write an empty file in that case cursor.moveToFirst(); ParcelableFileCache cache = - new ParcelableFileCache(mContext, "consolidate_public.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_public.pcl"); cache.writeCache(cursor.getCount(), new Iterator() { ParcelableKeyRing ring; @@ -1220,9 +1220,9 @@ public class ProviderHelper { mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); ParcelableFileCache cacheSecret = - new ParcelableFileCache(mContext, "consolidate_secret.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_secret.pcl"); ParcelableFileCache cachePublic = - new ParcelableFileCache(mContext, "consolidate_public.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_public.pcl"); // Set flag that we have a cached consolidation here try { @@ -1380,7 +1380,7 @@ public class ProviderHelper { public ArrayList getRegisteredApiApps() { Cursor cursor = mContentResolver.query(ApiApps.CONTENT_URI, null, null, null, null); - ArrayList packageNames = new ArrayList(); + ArrayList packageNames = new ArrayList<>(); try { if (cursor != null) { int packageNameCol = cursor.getColumnIndex(ApiApps.PACKAGE_NAME); @@ -1485,7 +1485,7 @@ public class ProviderHelper { } public Set getAllKeyIdsForApp(Uri uri) { - Set keyIds = new HashSet(); + Set keyIds = new HashSet<>(); Cursor cursor = mContentResolver.query(uri, null, null, null, null); try { @@ -1505,7 +1505,7 @@ public class ProviderHelper { } public Set getAllFingerprints(Uri uri) { - Set fingerprints = new HashSet(); + Set fingerprints = new HashSet<>(); String[] projection = new String[]{KeyRings.FINGERPRINT}; Cursor cursor = mContentResolver.query(uri, projection, null, null, null); try { -- cgit v1.2.3 From d6e4936fa54dc3577296dbadaeb556178dcad2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 29 Jan 2015 17:46:27 +0100 Subject: Introduce allowed keys table per API client --- .../keychain/provider/KeychainContract.java | 28 ++++++++++++++++++++++ .../keychain/provider/KeychainDatabase.java | 24 ++++++++++++++++++- .../keychain/provider/KeychainProvider.java | 22 ++++++++++++++--- 3 files changed, 70 insertions(+), 4 deletions(-) (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 f4e00c36c..e0313074c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -85,6 +85,11 @@ public class KeychainContract { String PACKAGE_NAME = "package_name"; // foreign key to api_apps.package_name } + interface ApiAppsAllowedKeysColumns { + String KEY_ID = "key_id"; // not a database id + String PACKAGE_NAME = "package_name"; // foreign key to api_apps.package_name + } + public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".provider"; private static final Uri BASE_CONTENT_URI_INTERNAL = Uri @@ -106,6 +111,7 @@ public class KeychainContract { public static final String BASE_API_APPS = "api_apps"; public static final String PATH_ACCOUNTS = "accounts"; + public static final String PATH_ALLOWED_KEYS = "allowed_keys"; public static class KeyRings implements BaseColumns, KeysColumns, UserPacketsColumns { public static final String MASTER_KEY_ID = KeysColumns.MASTER_KEY_ID; @@ -305,6 +311,28 @@ public class KeychainContract { } } + public static class ApiAllowedKeys implements ApiAppsAllowedKeysColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() + .appendPath(BASE_API_APPS).build(); + + /** + * Use if multiple items get returned + */ + public static final String CONTENT_TYPE + = "vnd.android.cursor.dir/vnd.org.sufficientlysecure.keychain.provider.api_apps.allowed_keys"; + + /** + * Use if a single item is returned + */ + public static final String CONTENT_ITEM_TYPE + = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.api_apps.allowed_keys"; + + public static Uri buildBaseUri(String packageName) { + return CONTENT_URI.buildUpon().appendEncodedPath(packageName).appendPath(PATH_ALLOWED_KEYS) + .build(); + } + } + public static class Certs implements CertsColumns, BaseColumns { public static final String USER_ID = UserPacketsColumns.USER_ID; public static final String SIGNER_UID = "signer_user_id"; 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 5ce5eec17..9e8f03a66 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -28,6 +28,7 @@ import android.provider.BaseColumns; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAllowedKeysColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns; @@ -52,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 = 7; + private static final int DATABASE_VERSION = 8; static Boolean apgHack = false; private Context mContext; @@ -64,6 +65,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { String CERTS = "certs"; String API_APPS = "api_apps"; String API_ACCOUNTS = "api_accounts"; + String API_ALLOWED_KEYS = "api_allowed_keys"; } private static final String CREATE_KEYRINGS_PUBLIC = @@ -166,6 +168,17 @@ public class KeychainDatabase extends SQLiteOpenHelper { + Tables.API_APPS + "(" + ApiAppsColumns.PACKAGE_NAME + ") ON DELETE CASCADE" + ")"; + private static final String CREATE_API_APPS_ALLOWED_KEYS = + "CREATE TABLE IF NOT EXISTS " + Tables.API_ALLOWED_KEYS + " (" + + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + ApiAppsAllowedKeysColumns.KEY_ID + " INTEGER, " + + ApiAppsAllowedKeysColumns.PACKAGE_NAME + " TEXT NOT NULL, " + + + "UNIQUE(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + "), " + + "FOREIGN KEY(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + ") REFERENCES " + + Tables.API_APPS + "(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + ") ON DELETE CASCADE" + + ")"; + KeychainDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); mContext = context; @@ -243,6 +256,15 @@ public class KeychainDatabase extends SQLiteOpenHelper { case 6: db.execSQL("ALTER TABLE user_ids ADD COLUMN type INTEGER"); db.execSQL("ALTER TABLE user_ids ADD COLUMN attribute_data BLOB"); + case 7: + // consolidate + case 8: + // new table for allowed key ids in API + try { + db.execSQL(CREATE_API_APPS_ALLOWED_KEYS); + } catch (Exception e) { + // never mind, the column probably already existed + } } // always do consolidate after upgrade 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 72475472e..4f263afc4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -31,6 +31,7 @@ import android.net.Uri; import android.text.TextUtils; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; @@ -63,9 +64,10 @@ public class KeychainProvider extends ContentProvider { private static final int KEY_RING_CERTS_SPECIFIC = 206; private static final int API_APPS = 301; - private static final int API_APPS_BY_PACKAGE_NAME = 303; - private static final int API_ACCOUNTS = 304; - private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 306; + private static final int API_APPS_BY_PACKAGE_NAME = 302; + private static final int API_ACCOUNTS = 303; + private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 304; + private static final int API_ALLOWED_KEYS = 305; private static final int KEY_RINGS_FIND_BY_EMAIL = 400; private static final int KEY_RINGS_FIND_BY_SUBKEY = 401; @@ -162,6 +164,8 @@ public class KeychainProvider extends ContentProvider { * * api_apps/_/accounts * api_apps/_/accounts/_ (account name) + * + * api_apps/_/allowed_keys * */ matcher.addURI(authority, KeychainContract.BASE_API_APPS, API_APPS); @@ -172,6 +176,9 @@ public class KeychainProvider extends ContentProvider { matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/" + KeychainContract.PATH_ACCOUNTS + "/*", API_ACCOUNTS_BY_ACCOUNT_NAME); + matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/" + + KeychainContract.PATH_ALLOWED_KEYS, API_ALLOWED_KEYS); + return matcher; } @@ -223,6 +230,9 @@ public class KeychainProvider extends ContentProvider { case API_ACCOUNTS_BY_ACCOUNT_NAME: return ApiAccounts.CONTENT_ITEM_TYPE; + case API_ALLOWED_KEYS: + return ApiAllowedKeys.CONTENT_ITEM_TYPE; + default: throw new UnsupportedOperationException("Unknown uri: " + uri); } @@ -613,6 +623,12 @@ public class KeychainProvider extends ContentProvider { qb.appendWhere(" AND " + Tables.API_ACCOUNTS + "." + ApiAccounts.ACCOUNT_NAME + " = "); qb.appendWhereEscapeString(uri.getLastPathSegment()); + break; + case API_ALLOWED_KEYS: + qb.setTables(Tables.API_ALLOWED_KEYS); + qb.appendWhere(Tables.API_ALLOWED_KEYS + "." + ApiAccounts.PACKAGE_NAME + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(1)); + break; default: throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); -- cgit v1.2.3 From fcd91d881eda698e69ca00ed6cdedc1e0a9d2394 Mon Sep 17 00:00:00 2001 From: ligi Date: Thu, 29 Jan 2015 20:30:26 +0100 Subject: Add explicit casting to be able to compile with java8 --- .../java/org/sufficientlysecure/keychain/provider/KeychainProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider') 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 72475472e..1fc14e59f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -683,7 +683,7 @@ public class KeychainProvider extends ContentProvider { )) { throw new AssertionError("Incorrect type for user packet! This is a bug!"); } - if (values.get(UserPacketsColumns.RANK) == 0 && values.get(UserPacketsColumns.USER_ID) == null) { + if (((Number)values.get(UserPacketsColumns.RANK)).intValue() == 0 && values.get(UserPacketsColumns.USER_ID) == null) { throw new AssertionError("Rank 0 user packet must be a user id!"); } db.insertOrThrow(Tables.USER_PACKETS, null, values); -- cgit v1.2.3 From 38f7950d90c49ff27dcf2afb651337c2f4f2b663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 29 Jan 2015 21:00:58 +0100 Subject: Saving of allowed keys --- .../keychain/provider/KeychainContract.java | 6 ---- .../keychain/provider/KeychainDatabase.java | 4 ++- .../keychain/provider/KeychainProvider.java | 30 ++++++++++++++-- .../keychain/provider/ProviderHelper.java | 40 ++++++++++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) (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 e0313074c..5856589c4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -321,12 +321,6 @@ public class KeychainContract { public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.org.sufficientlysecure.keychain.provider.api_apps.allowed_keys"; - /** - * Use if a single item is returned - */ - public static final String CONTENT_ITEM_TYPE - = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.api_apps.allowed_keys"; - public static Uri buildBaseUri(String packageName) { return CONTENT_URI.buildUpon().appendEncodedPath(packageName).appendPath(PATH_ALLOWED_KEYS) .build(); 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 9e8f03a66..d34cc74a3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -174,7 +174,8 @@ public class KeychainDatabase extends SQLiteOpenHelper { + ApiAppsAllowedKeysColumns.KEY_ID + " INTEGER, " + ApiAppsAllowedKeysColumns.PACKAGE_NAME + " TEXT NOT NULL, " - + "UNIQUE(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + "), " + + "UNIQUE(" + ApiAppsAllowedKeysColumns.KEY_ID + ", " + + ApiAppsAllowedKeysColumns.PACKAGE_NAME + "), " + "FOREIGN KEY(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + ") REFERENCES " + Tables.API_APPS + "(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + ") ON DELETE CASCADE" + ")"; @@ -208,6 +209,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { db.execSQL(CREATE_CERTS); db.execSQL(CREATE_API_APPS); db.execSQL(CREATE_API_APPS_ACCOUNTS); + db.execSQL(CREATE_API_APPS_ALLOWED_KEYS); } @Override 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 4f263afc4..6bd88570f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -231,7 +231,7 @@ public class KeychainProvider extends ContentProvider { return ApiAccounts.CONTENT_ITEM_TYPE; case API_ALLOWED_KEYS: - return ApiAllowedKeys.CONTENT_ITEM_TYPE; + return ApiAllowedKeys.CONTENT_TYPE; default: throw new UnsupportedOperationException("Unknown uri: " + uri); @@ -717,7 +717,7 @@ public class KeychainProvider extends ContentProvider { db.insertOrThrow(Tables.API_APPS, null, values); break; - case API_ACCOUNTS: + case API_ACCOUNTS: { // set foreign key automatically based on given uri // e.g., api_apps/com.example.app/accounts/ String packageName = uri.getPathSegments().get(1); @@ -725,12 +725,21 @@ public class KeychainProvider extends ContentProvider { db.insertOrThrow(Tables.API_ACCOUNTS, null, values); break; + } + case API_ALLOWED_KEYS: { + // set foreign key automatically based on given uri + // e.g., api_apps/com.example.app/allowed_keys/ + String packageName = uri.getPathSegments().get(1); + values.put(ApiAllowedKeys.PACKAGE_NAME, packageName); + db.insertOrThrow(Tables.API_ALLOWED_KEYS, null, values); + break; + } default: throw new UnsupportedOperationException("Unknown uri: " + uri); } - if(keyId != null) { + if (keyId != null) { uri = KeyRings.buildGenericKeyRingUri(keyId); rowUri = uri; } @@ -793,6 +802,10 @@ public class KeychainProvider extends ContentProvider { count = db.delete(Tables.API_ACCOUNTS, buildDefaultApiAccountsSelection(uri, additionalSelection), selectionArgs); break; + case API_ALLOWED_KEYS: + count = db.delete(Tables.API_ALLOWED_KEYS, buildDefaultApiAllowedKeysSelection(uri, additionalSelection), + selectionArgs); + break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); } @@ -885,4 +898,15 @@ public class KeychainProvider extends ContentProvider { + andSelection; } + private String buildDefaultApiAllowedKeysSelection(Uri uri, String selection) { + String packageName = DatabaseUtils.sqlEscapeString(uri.getPathSegments().get(1)); + + String andSelection = ""; + if (!TextUtils.isEmpty(selection)) { + andSelection = " AND (" + selection + ")"; + } + + return ApiAllowedKeys.PACKAGE_NAME + "=" + packageName + andSelection; + } + } 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 a229f454f..db458254c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; +import org.sufficientlysecure.keychain.remote.ui.AppSettingsAllowedKeys; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; import org.sufficientlysecure.keychain.util.Preferences; @@ -50,6 +51,7 @@ import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; import org.sufficientlysecure.keychain.pgp.WrappedSignature; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; @@ -1504,6 +1506,44 @@ public class ProviderHelper { return keyIds; } + public Set getAllowedKeyIdsForApp(Uri uri) { + Set keyIds = new HashSet<>(); + + Cursor cursor = mContentResolver.query(uri, null, null, null, null); + try { + if (cursor != null) { + int keyIdColumn = cursor.getColumnIndex(KeychainContract.ApiAllowedKeys.KEY_ID); + while (cursor.moveToNext()) { + keyIds.add(cursor.getLong(keyIdColumn)); + } + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + + return keyIds; + } + + public void saveAllowedKeyIdsForApp(Uri uri, Set allowedKeyIds) + throws RemoteException, OperationApplicationException { + ArrayList ops = new ArrayList<>(); + + // clear table + ops.add(ContentProviderOperation.newDelete(uri) + .build()); + + // re-insert allowed key ids + for (Long keyId : allowedKeyIds) { + ops.add(ContentProviderOperation.newInsert(uri) + .withValue(ApiAllowedKeys.KEY_ID, keyId) + .build()); + } + + getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY, ops); + } + public Set getAllFingerprints(Uri uri) { Set fingerprints = new HashSet<>(); String[] projection = new String[]{KeyRings.FINGERPRINT}; -- cgit v1.2.3 From 464f7c671834cd01c83b5453437c0df451510a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 30 Jan 2015 10:47:40 +0100 Subject: Fix saving of allowed keys --- .../keychain/provider/ProviderHelper.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 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 db458254c..2bf62c2e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1310,7 +1310,6 @@ public class ProviderHelper { progress.setProgress(100, 100); log.add(LogType.MSG_CON_SUCCESS, indent); - indent -= 1; return new ConsolidateResult(ConsolidateResult.RESULT_OK, log); @@ -1528,20 +1527,15 @@ public class ProviderHelper { public void saveAllowedKeyIdsForApp(Uri uri, Set allowedKeyIds) throws RemoteException, OperationApplicationException { - ArrayList ops = new ArrayList<>(); - - // clear table - ops.add(ContentProviderOperation.newDelete(uri) - .build()); + // wipe whole table of allowed keys for this account + mContentResolver.delete(uri, null, null); // re-insert allowed key ids for (Long keyId : allowedKeyIds) { - ops.add(ContentProviderOperation.newInsert(uri) - .withValue(ApiAllowedKeys.KEY_ID, keyId) - .build()); + ContentValues values = new ContentValues(); + values.put(ApiAllowedKeys.KEY_ID, keyId); + mContentResolver.insert(uri, values); } - - getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY, ops); } public Set getAllFingerprints(Uri uri) { -- cgit v1.2.3 From e651a392795caa395b060946b0cfaca5a5b41ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 30 Jan 2015 10:59:57 +0100 Subject: Rename app setting classes for consistency --- .../java/org/sufficientlysecure/keychain/provider/ProviderHelper.java | 1 - 1 file changed, 1 deletion(-) (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 2bf62c2e0..10e0c3dc8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -33,7 +33,6 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; -import org.sufficientlysecure.keychain.remote.ui.AppSettingsAllowedKeys; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; import org.sufficientlysecure.keychain.util.Preferences; -- cgit v1.2.3 From 5466d1e9802815726d713bca2aeabaff2861519c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 31 Jan 2015 18:26:20 +0100 Subject: prevent recursive consolidate --- .../sufficientlysecure/keychain/provider/ProviderHelper.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 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 a229f454f..f23006a94 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1053,6 +1053,11 @@ public class ProviderHelper { log.add(LogType.MSG_CON, indent); indent += 1; + if (mConsolidateCritical) { + log.add(LogType.MSG_CON_RECURSIVE, indent); + return new ConsolidateResult(ConsolidateResult.RESULT_OK, log); + } + progress.setProgress(R.string.progress_con_saving, 0, 100); // The consolidate operation can never be cancelled! @@ -1219,13 +1224,11 @@ public class ProviderHelper { log.add(LogType.MSG_CON_DB_CLEAR, indent); mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); - ParcelableFileCache cacheSecret = - new ParcelableFileCache<>(mContext, "consolidate_secret.pcl"); - ParcelableFileCache cachePublic = - new ParcelableFileCache<>(mContext, "consolidate_public.pcl"); + ParcelableFileCache cacheSecret, cachePublic; // Set flag that we have a cached consolidation here try { + cacheSecret = new ParcelableFileCache<>(mContext, "consolidate_secret.pcl"); IteratorWithSize itSecrets = cacheSecret.readCache(false); int numSecrets = itSecrets.getSize(); @@ -1253,6 +1256,7 @@ public class ProviderHelper { try { + cachePublic = new ParcelableFileCache<>(mContext, "consolidate_public.pcl"); IteratorWithSize itPublics = cachePublic.readCache(); int numPublics = itPublics.getSize(); -- cgit v1.2.3 From 7b24ee7b55db99467dd63e631ba55a27d08587d5 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 1 Feb 2015 23:14:26 +0100 Subject: rewrite PgpSignEncrypt data flow - introduce high-level SignEncryptOperation for uri to uri signing/encryption - use SignEncryptParcel for high-level operation parameters - use PgpSignEncryptInput plus streams for low-level operation parameters - get rid of all sign/encrypt logic in KeychainIntentService --- .../keychain/provider/KeychainDatabase.java | 2 +- .../keychain/provider/KeychainProvider.java | 2 +- .../keychain/provider/ProviderHelper.java | 24 +++++++++++----------- 3 files changed, 14 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 d34cc74a3..b88cd6006 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -28,8 +28,8 @@ import android.provider.BaseColumns; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAllowedKeysColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAllowedKeysColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; 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 2ffc8c2ca..2601c1f69 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -31,8 +31,8 @@ import android.net.Uri; import android.text.TextUtils; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; 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 2ba7a19dc..18efa2b80 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -30,13 +30,13 @@ import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; -import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; -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.results.ConsolidateResult; +import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; +import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; +import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; @@ -44,11 +44,11 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.PgpHelper; -import org.sufficientlysecure.keychain.operations.ImportExportOperation; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; import org.sufficientlysecure.keychain.pgp.WrappedSignature; +import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; @@ -56,15 +56,15 @@ 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.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AppSettings; -import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; -import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; -import org.sufficientlysecure.keychain.operations.results.ConsolidateResult; -import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; -import org.sufficientlysecure.keychain.util.ParcelableFileCache; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ParcelableFileCache; +import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; +import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.ProgressFixedScaler; import org.sufficientlysecure.keychain.util.ProgressScaler; import org.sufficientlysecure.keychain.util.Utf8Util; -- cgit v1.2.3 From e5bb7a35b5202cf8ef13325d86ef82f2583700b7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 26 Feb 2015 18:53:16 +0100 Subject: save revocation instead of self-cert for revoked uids --- .../keychain/provider/ProviderHelper.java | 31 +++++++++++++--------- 1 file changed, 19 insertions(+), 12 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 18efa2b80..d947ae053 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -473,7 +473,7 @@ public class ProviderHelper { item.selfCert = cert; item.isPrimary = cert.isPrimaryUserId(); } else { - item.isRevoked = true; + item.selfRevocation = cert; log(LogType.MSG_IP_UID_REVOKED); } continue; @@ -569,10 +569,11 @@ public class ProviderHelper { // NOTE self-certificates are already verified during canonicalization, // AND we know there is at most one cert plus at most one revocation + // AND the revocation only exists if there is no newer certification if (!cert.isRevocation()) { item.selfCert = cert; } else { - item.isRevoked = true; + item.selfRevocation = cert; log(LogType.MSG_IP_UAT_REVOKED); } continue; @@ -643,16 +644,21 @@ public class ProviderHelper { for (int userIdRank = 0; userIdRank < uids.size(); userIdRank++) { UserPacketItem item = uids.get(userIdRank); operations.add(buildUserIdOperations(masterKeyId, item, userIdRank)); - if (item.selfCert != null) { - // TODO get rid of "self verified" status? this cannot even happen anymore! - operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfCert, - selfCertsAreTrusted ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF)); + + if (item.selfCert == null) { + throw new AssertionError("User ids MUST be self-certified at this point!!"); } - // don't bother with trusted certs if the uid is revoked, anyways - if (item.isRevoked) { + + if (item.selfRevocation != null) { + operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfRevocation, + Certs.VERIFIED_SELF)); + // don't bother with trusted certs if the uid is revoked, anyways continue; } + operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfCert, + selfCertsAreTrusted ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF)); + // iterate over signatures for (int i = 0; i < item.trustedCerts.size() ; i++) { WrappedSignature sig = item.trustedCerts.valueAt(i); @@ -711,15 +717,16 @@ public class ProviderHelper { String userId; byte[] attributeData; boolean isPrimary = false; - boolean isRevoked = false; WrappedSignature selfCert; + WrappedSignature selfRevocation; LongSparseArray trustedCerts = new LongSparseArray<>(); @Override public int compareTo(UserPacketItem o) { // revoked keys always come last! - if (isRevoked != o.isRevoked) { - return isRevoked ? 1 : -1; + //noinspection DoubleNegation + 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. // we compare for null values here, so != is the correct operator! @@ -1353,7 +1360,7 @@ public class ProviderHelper { values.put(UserPackets.USER_ID, item.userId); values.put(UserPackets.ATTRIBUTE_DATA, item.attributeData); values.put(UserPackets.IS_PRIMARY, item.isPrimary); - values.put(UserPackets.IS_REVOKED, item.isRevoked); + values.put(UserPackets.IS_REVOKED, item.selfRevocation != null); values.put(UserPackets.RANK, rank); Uri uri = UserPackets.buildUserIdsUri(masterKeyId); -- cgit v1.2.3