Merge remote-tracking branch 'origin/development' into development
This commit is contained in:
@@ -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,22 @@ 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";
|
||||
|
||||
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";
|
||||
|
||||
@@ -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,18 @@ 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.KEY_ID + ", "
|
||||
+ 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;
|
||||
@@ -195,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
|
||||
@@ -243,6 +258,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
|
||||
|
||||
@@ -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
|
||||
* </pre>
|
||||
*/
|
||||
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_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 + ")");
|
||||
@@ -683,7 +699,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);
|
||||
@@ -701,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);
|
||||
@@ -709,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;
|
||||
}
|
||||
@@ -777,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);
|
||||
}
|
||||
@@ -869,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,6 +50,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;
|
||||
@@ -1312,7 +1313,6 @@ public class ProviderHelper {
|
||||
|
||||
progress.setProgress(100, 100);
|
||||
log.add(LogType.MSG_CON_SUCCESS, indent);
|
||||
indent -= 1;
|
||||
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_OK, log);
|
||||
|
||||
@@ -1508,6 +1508,39 @@ public class ProviderHelper {
|
||||
return keyIds;
|
||||
}
|
||||
|
||||
public Set<Long> getAllowedKeyIdsForApp(Uri uri) {
|
||||
Set<Long> 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<Long> allowedKeyIds)
|
||||
throws RemoteException, OperationApplicationException {
|
||||
// wipe whole table of allowed keys for this account
|
||||
mContentResolver.delete(uri, null, null);
|
||||
|
||||
// re-insert allowed key ids
|
||||
for (Long keyId : allowedKeyIds) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(ApiAllowedKeys.KEY_ID, keyId);
|
||||
mContentResolver.insert(uri, values);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getAllFingerprints(Uri uri) {
|
||||
Set<String> fingerprints = new HashSet<>();
|
||||
String[] projection = new String[]{KeyRings.FINGERPRINT};
|
||||
|
||||
Reference in New Issue
Block a user