diff options
Diffstat (limited to 'OpenPGP-Keychain')
5 files changed, 109 insertions, 78 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index e6e106ba6..9eeb57222 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -83,10 +83,9 @@ public class KeychainContract { public static final String PATH_UNIFIED = "unified"; - public static final String PATH_BY_MASTER_KEY_ID = "master_key_id"; - public static final String PATH_BY_KEY_ID = "key_id"; - public static final String PATH_BY_EMAILS = "emails"; - public static final String PATH_BY_LIKE_EMAIL = "like_email"; + public static final String PATH_FIND = "find"; + public static final String PATH_BY_EMAIL = "email"; + public static final String PATH_BY_SUBKEY = "subkey"; public static final String PATH_PUBLIC = "public"; public static final String PATH_SECRET = "secret"; @@ -109,20 +108,24 @@ public class KeychainContract { public static Uri buildUnifiedKeyRingsUri() { return CONTENT_URI.buildUpon().appendPath(PATH_UNIFIED).build(); } - public static Uri buildUnifiedKeyRingsByEmailUri(String email) { - return CONTENT_URI.buildUpon().appendPath("email:" + email).build(); - } public static Uri buildGenericKeyRingUri(String masterKeyId) { return CONTENT_URI.buildUpon().appendPath(masterKeyId).build(); } - public static Uri buildUnifiedKeyRingUri(String masterKeyId) { return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_UNIFIED).build(); } public static Uri buildUnifiedKeyRingUri(Uri uri) { return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_UNIFIED).build(); } + + public static Uri buildUnifiedKeyRingsFindByEmailUri(String email) { + return CONTENT_URI.buildUpon().appendPath(PATH_FIND).appendPath(PATH_BY_EMAIL).appendPath(email).build(); + } + public static Uri buildUnifiedKeyRingsFindBySubkeyUri(String subkey) { + return CONTENT_URI.buildUpon().appendPath(PATH_FIND).appendPath(PATH_BY_SUBKEY).appendPath(subkey).build(); + } + } public static class KeyRingData implements KeyRingsColumns, BaseColumns { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 8b1ee4886..a14b5b3de 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -57,7 +57,10 @@ public class KeychainProvider extends ContentProvider { private static final int API_ACCOUNTS = 304; private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 306; - // private static final int DATA_STREAM = 401; + private static final int KEY_RINGS_FIND_BY_EMAIL = 400; + private static final int KEY_RINGS_FIND_BY_SUBKEY = 401; + + // private static final int DATA_STREAM = 501; protected UriMatcher mUriMatcher; @@ -86,6 +89,20 @@ public class KeychainProvider extends ContentProvider { KEY_RINGS_PUBLIC); /** + * find by criteria other than master key id + * + * key_rings/find/email/_ + * key_rings/find/subkey/_ + * + */ + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" + + KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_EMAIL + "/*", + KEY_RINGS_FIND_BY_EMAIL); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" + + KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_SUBKEY + "/*", + KEY_RINGS_FIND_BY_SUBKEY); + + /** * list key_ring specifics * * <pre> @@ -200,7 +217,6 @@ public class KeychainProvider extends ContentProvider { Log.v(Constants.TAG, "query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - SQLiteDatabase db = mKeychainDatabase.getReadableDatabase(); int match = mUriMatcher.match(uri); @@ -209,7 +225,9 @@ public class KeychainProvider extends ContentProvider { switch (match) { case KEY_RING_UNIFIED: - case KEY_RINGS_UNIFIED: { + case KEY_RINGS_UNIFIED: + case KEY_RINGS_FIND_BY_EMAIL: + case KEY_RINGS_FIND_BY_SUBKEY: { HashMap<String, String> projectionMap = new HashMap<String, String>(); projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id"); projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); @@ -242,13 +260,64 @@ public class KeychainProvider extends ContentProvider { ); qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0"); - if(match == KEY_RING_UNIFIED) { - qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(1)); - } else if (TextUtils.isEmpty(sortOrder)) { + switch(match) { + case KEY_RING_UNIFIED: { + qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(1)); + break; + } + case KEY_RINGS_FIND_BY_SUBKEY: { + try { + String subkey = Long.valueOf(uri.getLastPathSegment()).toString(); + qb.appendWhere(" AND EXISTS (" + + " SELECT 1 FROM " + Tables.KEYS + " AS tmp" + + " WHERE tmp." + UserIds.MASTER_KEY_ID + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND tmp." + Keys.KEY_ID + " = " + subkey + "" + + ")"); + } catch(NumberFormatException e) { + Log.e(Constants.TAG, "Malformed find by subkey query!", e); + qb.appendWhere(" AND 0"); + } + break; + } + case KEY_RINGS_FIND_BY_EMAIL: { + String chunks[] = uri.getLastPathSegment().split(" *, *"); + boolean gotCondition = false; + String emailWhere = ""; + // JAVA ♥ + for (int i = 0; i < chunks.length; ++i) { + if (chunks[i].length() == 0) { + continue; + } + if (i != 0) { + emailWhere += " OR "; + } + emailWhere += "tmp." + UserIds.USER_ID + " LIKE "; + // match '*<email>', 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 + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND (" + emailWhere + ")" + + ")"); + } else { + // TODO better way to do this? + Log.e(Constants.TAG, "Malformed find by email query!"); + qb.appendWhere(" AND 0"); + } + break; + } + } + + if (TextUtils.isEmpty(sortOrder)) { sortOrder = - Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL DESC" - + Tables.USER_IDS + "." + UserIds.USER_ID + " ASC"; + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL ASC, " + + Tables.USER_IDS + "." + UserIds.USER_ID + " ASC"; } // uri to watch is all /key_rings/ @@ -256,33 +325,6 @@ public class KeychainProvider extends ContentProvider { break; } - /*case SECRET_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_EMAILS: - qb = buildKeyRingQuery(qb, match); - - String emails = uri.getLastPathSegment(); - String chunks[] = emails.split(" *, *"); - boolean gotCondition = false; - String emailWhere = ""; - for (int i = 0; i < chunks.length; ++i) { - if (chunks[i].length() == 0) { - continue; - } - if (i != 0) { - emailWhere += " OR "; - } - emailWhere += "tmp." + UserIds.USER_ID + " LIKE "; - // match '*<email>', 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 tmp." + Base._ID + " FROM " - + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIds.KEY_RING_ROW_ID - + " = " + Tables.KEY_RINGS + "." + Base._ID + " AND (" + emailWhere - + "))"); - }*/ case KEY_RING_KEYS: { HashMap<String, String> projectionMap = new HashMap<String, String>(); @@ -387,7 +429,7 @@ public class KeychainProvider extends ContentProvider { break; default: - throw new IllegalArgumentException("Unknown URI " + uri); + throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); } @@ -399,6 +441,7 @@ public class KeychainProvider extends ContentProvider { orderBy = sortOrder; } + SQLiteDatabase db = mKeychainDatabase.getReadableDatabase(); Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, having, orderBy); // Tell the cursor what uri to watch, so it knows when its source data changes diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index ccae6b2f2..c640bdb7c 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -61,15 +61,15 @@ public class OpenPgpService extends RemoteService { ArrayList<Long> keyIds = new ArrayList<Long>(); boolean missingUserIdsCheck = false; - boolean dublicateUserIdsCheck = false; + boolean duplicateUserIdsCheck = false; ArrayList<String> missingUserIds = new ArrayList<String>(); - ArrayList<String> dublicateUserIds = new ArrayList<String>(); + ArrayList<String> duplicateUserIds = new ArrayList<String>(); for (String email : encryptionUserIds) { - Uri uri = KeychainContract.KeyRings.buildUnifiedKeyRingsByEmailUri(email); + Uri uri = KeyRings.buildUnifiedKeyRingsFindByEmailUri(email); Cursor cur = getContentResolver().query(uri, null, null, null, null); if (cur.moveToFirst()) { - long id = cur.getLong(cur.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID)); + long id = cur.getLong(cur.getColumnIndex(KeyRings.MASTER_KEY_ID)); keyIds.add(id); } else { missingUserIdsCheck = true; @@ -77,8 +77,8 @@ public class OpenPgpService extends RemoteService { Log.d(Constants.TAG, "user id missing"); } if (cur.moveToNext()) { - dublicateUserIdsCheck = true; - dublicateUserIds.add(email); + duplicateUserIdsCheck = true; + duplicateUserIds.add(email); Log.d(Constants.TAG, "more than one user id with the same email"); } } @@ -90,13 +90,13 @@ public class OpenPgpService extends RemoteService { } // allow the user to verify pub key selection - if (missingUserIdsCheck || dublicateUserIdsCheck) { + if (missingUserIdsCheck || duplicateUserIdsCheck) { // build PendingIntent Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS); intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray); intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds); - intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, dublicateUserIds); + intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, duplicateUserIds); intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 0ec4c1239..962b304c7 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -46,6 +46,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import java.util.Date; @@ -170,15 +171,11 @@ public class PassphraseCacheService extends Service { // try to get master key id which is used as an identifier for cached passphrases long masterKeyId = keyId; if (masterKeyId != Id.key.symmetric) { - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(this, keyId); - if (keyRing == null) { + masterKeyId = ProviderHelper.getMasterKeyId(this, + KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId))); + // Failure + if(masterKeyId == 0) return null; - } - PGPSecretKey masterKey = keyRing.getSecretKey(); - if (masterKey == null) { - return null; - } - masterKeyId = masterKey.getKeyID(); } Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + masterKeyId); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index f749a4c1c..11fe4a908 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -160,23 +160,11 @@ public class EncryptAsymmetricFragment extends Fragment { if (preselectedEncryptionKeyIds != null) { Vector<Long> goodIds = new Vector<Long>(); for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) { - // TODO: don't use bouncy castle objects! - - PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId(getActivity(), - preselectedEncryptionKeyIds[i]); - PGPPublicKey masterKey; - if (keyRing == null) { - continue; - } - masterKey = keyRing.getPublicKey(); - if (masterKey == null) { - continue; - } - Vector<PGPPublicKey> encryptKeys = PgpKeyHelper.getUsableEncryptKeys(keyRing); - if (encryptKeys.size() == 0) { - continue; - } - goodIds.add(masterKey.getKeyID()); + long id = ProviderHelper.getMasterKeyId(getActivity(), + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(preselectedEncryptionKeyIds[i])) + ); + // TODO check for available encrypt keys... is this even relevant? + goodIds.add(id); } if (goodIds.size() > 0) { long[] keyIds = new long[goodIds.size()]; |