blob: 591d0a5bb80a7fb21ff0223e94ae36ce3d851088 [file] [log] [blame]
Eran Messeri5844b632017-11-03 10:28:34 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.keychain.internal;
18
19import android.content.ContentValues;
20import android.content.Context;
21import android.content.pm.PackageManager;
22import android.database.Cursor;
23import android.database.DatabaseUtils;
24import android.database.sqlite.SQLiteDatabase;
25import android.database.sqlite.SQLiteOpenHelper;
26import android.util.Log;
27
28public class GrantsDatabase {
29 private static final String TAG = "KeyChain";
30
31 private static final String DATABASE_NAME = "grants.db";
32 private static final int DATABASE_VERSION = 1;
33 private static final String TABLE_GRANTS = "grants";
34 private static final String GRANTS_ALIAS = "alias";
35 private static final String GRANTS_GRANTEE_UID = "uid";
36
37 private static final String SELECTION_COUNT_OF_MATCHING_GRANTS =
38 "SELECT COUNT(*) FROM "
39 + TABLE_GRANTS
40 + " WHERE "
41 + GRANTS_GRANTEE_UID
42 + "=? AND "
43 + GRANTS_ALIAS
44 + "=?";
45
46 private static final String SELECT_GRANTS_BY_UID_AND_ALIAS =
47 GRANTS_GRANTEE_UID + "=? AND " + GRANTS_ALIAS + "=?";
48
49 private static final String SELECTION_GRANTS_BY_UID = GRANTS_GRANTEE_UID + "=?";
50
51 private static final String SELECTION_GRANTS_BY_ALIAS = GRANTS_ALIAS + "=?";
52
53 public DatabaseHelper mDatabaseHelper;
54
55 private class DatabaseHelper extends SQLiteOpenHelper {
56 public DatabaseHelper(Context context) {
57 super(context, DATABASE_NAME, null /* CursorFactory */, DATABASE_VERSION);
58 }
59
60 @Override
61 public void onCreate(final SQLiteDatabase db) {
62 db.execSQL(
63 "CREATE TABLE "
64 + TABLE_GRANTS
65 + " ( "
66 + GRANTS_ALIAS
67 + " STRING NOT NULL, "
68 + GRANTS_GRANTEE_UID
69 + " INTEGER NOT NULL, "
70 + "UNIQUE ("
71 + GRANTS_ALIAS
72 + ","
73 + GRANTS_GRANTEE_UID
74 + "))");
75 }
76
77 @Override
78 public void onUpgrade(final SQLiteDatabase db, int oldVersion, final int newVersion) {
79 Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
80
81 if (oldVersion == 1) {
82 // the first upgrade step goes here
83 oldVersion++;
84 }
85 }
86 }
87
88 public GrantsDatabase(Context context) {
89 mDatabaseHelper = new DatabaseHelper(context);
90 }
91
92 public void destroy() {
93 mDatabaseHelper.close();
94 mDatabaseHelper = null;
95 }
96
97 boolean hasGrantInternal(final SQLiteDatabase db, final int uid, final String alias) {
98 final long numMatches =
99 DatabaseUtils.longForQuery(
100 db,
101 SELECTION_COUNT_OF_MATCHING_GRANTS,
102 new String[] {String.valueOf(uid), alias});
103 return numMatches > 0;
104 }
105
106 public boolean hasGrant(final int uid, final String alias) {
107 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
108 return hasGrantInternal(db, uid, alias);
109 }
110
111 public void setGrant(final int uid, final String alias, final boolean value) {
112 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
113 if (value) {
114 if (!hasGrantInternal(db, uid, alias)) {
115 final ContentValues values = new ContentValues();
116 values.put(GRANTS_ALIAS, alias);
117 values.put(GRANTS_GRANTEE_UID, uid);
118 db.insert(TABLE_GRANTS, GRANTS_ALIAS, values);
119 }
120 } else {
121 db.delete(
122 TABLE_GRANTS,
123 SELECT_GRANTS_BY_UID_AND_ALIAS,
124 new String[] {String.valueOf(uid), alias});
125 }
126 }
127
128 public void removeGrantsForAlias(String alias) {
129 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
130 db.delete(TABLE_GRANTS, SELECTION_GRANTS_BY_ALIAS, new String[] {alias});
131 }
132
133 public void removeAllGrants() {
134 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
135 db.delete(TABLE_GRANTS, null /* whereClause */, null /* whereArgs */);
136 }
137
138 public void purgeOldGrants(PackageManager pm) {
139 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
140 Cursor cursor = null;
141 db.beginTransaction();
142 try {
143 cursor =
144 db.query(
145 TABLE_GRANTS,
146 new String[] {GRANTS_GRANTEE_UID},
147 null,
148 null,
149 GRANTS_GRANTEE_UID,
150 null,
151 null);
152 while (cursor.moveToNext()) {
153 final int uid = cursor.getInt(0);
154 final boolean packageExists = pm.getPackagesForUid(uid) != null;
155 if (packageExists) {
156 continue;
157 }
158 Log.d(TAG, String.format(
159 "deleting grants for UID %d because its package is no longer installed",
160 uid));
161 db.delete(
162 TABLE_GRANTS,
163 SELECTION_GRANTS_BY_UID,
164 new String[] {Integer.toString(uid)});
165 }
166 db.setTransactionSuccessful();
167 } finally {
168 if (cursor != null) {
169 cursor.close();
170 }
171 db.endTransaction();
172 }
173 }
174}