android: Add property for selected apps to VPN profiles
[strongswan.git] / src / frontends / android / app / src / main / java / org / strongswan / android / data / VpnProfileDataSource.java
1 /*
2 * Copyright (C) 2012-2017 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 package org.strongswan.android.data;
19
20 import android.content.ContentValues;
21 import android.content.Context;
22 import android.database.Cursor;
23 import android.database.SQLException;
24 import android.database.sqlite.SQLiteDatabase;
25 import android.database.sqlite.SQLiteOpenHelper;
26 import android.database.sqlite.SQLiteQueryBuilder;
27 import android.util.Log;
28
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.UUID;
32
33 public class VpnProfileDataSource
34 {
35 private static final String TAG = VpnProfileDataSource.class.getSimpleName();
36 public static final String KEY_ID = "_id";
37 public static final String KEY_UUID = "_uuid";
38 public static final String KEY_NAME = "name";
39 public static final String KEY_GATEWAY = "gateway";
40 public static final String KEY_VPN_TYPE = "vpn_type";
41 public static final String KEY_USERNAME = "username";
42 public static final String KEY_PASSWORD = "password";
43 public static final String KEY_CERTIFICATE = "certificate";
44 public static final String KEY_USER_CERTIFICATE = "user_certificate";
45 public static final String KEY_MTU = "mtu";
46 public static final String KEY_PORT = "port";
47 public static final String KEY_SPLIT_TUNNELING = "split_tunneling";
48 public static final String KEY_LOCAL_ID = "local_id";
49 public static final String KEY_REMOTE_ID = "remote_id";
50 public static final String KEY_EXCLUDED_SUBNETS = "excluded_subnets";
51 public static final String KEY_INCLUDED_SUBNETS = "included_subnets";
52 public static final String KEY_SELECTED_APPS = "selected_apps";
53 public static final String KEY_SELECTED_APPS_LIST = "selected_apps_list";
54
55 private DatabaseHelper mDbHelper;
56 private SQLiteDatabase mDatabase;
57 private final Context mContext;
58
59 private static final String DATABASE_NAME = "strongswan.db";
60 private static final String TABLE_VPNPROFILE = "vpnprofile";
61
62 private static final int DATABASE_VERSION = 12;
63
64 public static final String DATABASE_CREATE =
65 "CREATE TABLE " + TABLE_VPNPROFILE + " (" +
66 KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
67 KEY_UUID + " TEXT UNIQUE," +
68 KEY_NAME + " TEXT NOT NULL," +
69 KEY_GATEWAY + " TEXT NOT NULL," +
70 KEY_VPN_TYPE + " TEXT NOT NULL," +
71 KEY_USERNAME + " TEXT," +
72 KEY_PASSWORD + " TEXT," +
73 KEY_CERTIFICATE + " TEXT," +
74 KEY_USER_CERTIFICATE + " TEXT," +
75 KEY_MTU + " INTEGER," +
76 KEY_PORT + " INTEGER," +
77 KEY_SPLIT_TUNNELING + " INTEGER," +
78 KEY_LOCAL_ID + " TEXT," +
79 KEY_REMOTE_ID + " TEXT," +
80 KEY_EXCLUDED_SUBNETS + " TEXT," +
81 KEY_INCLUDED_SUBNETS + " TEXT," +
82 KEY_SELECTED_APPS + " INTEGER," +
83 KEY_SELECTED_APPS_LIST + " TEXT" +
84 ");";
85 private static final String[] ALL_COLUMNS = new String[] {
86 KEY_ID,
87 KEY_UUID,
88 KEY_NAME,
89 KEY_GATEWAY,
90 KEY_VPN_TYPE,
91 KEY_USERNAME,
92 KEY_PASSWORD,
93 KEY_CERTIFICATE,
94 KEY_USER_CERTIFICATE,
95 KEY_MTU,
96 KEY_PORT,
97 KEY_SPLIT_TUNNELING,
98 KEY_LOCAL_ID,
99 KEY_REMOTE_ID,
100 KEY_EXCLUDED_SUBNETS,
101 KEY_INCLUDED_SUBNETS,
102 KEY_SELECTED_APPS,
103 KEY_SELECTED_APPS_LIST,
104 };
105
106 private static class DatabaseHelper extends SQLiteOpenHelper
107 {
108 public DatabaseHelper(Context context)
109 {
110 super(context, DATABASE_NAME, null, DATABASE_VERSION);
111 }
112
113 @Override
114 public void onCreate(SQLiteDatabase database)
115 {
116 database.execSQL(DATABASE_CREATE);
117 }
118
119 @Override
120 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
121 {
122 Log.w(TAG, "Upgrading database from version " + oldVersion +
123 " to " + newVersion);
124 if (oldVersion < 2)
125 {
126 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_USER_CERTIFICATE +
127 " TEXT;");
128 }
129 if (oldVersion < 3)
130 {
131 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_VPN_TYPE +
132 " TEXT DEFAULT '';");
133 }
134 if (oldVersion < 4)
135 { /* remove NOT NULL constraint from username column */
136 updateColumns(db);
137 }
138 if (oldVersion < 5)
139 {
140 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_MTU +
141 " INTEGER;");
142 }
143 if (oldVersion < 6)
144 {
145 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_PORT +
146 " INTEGER;");
147 }
148 if (oldVersion < 7)
149 {
150 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_SPLIT_TUNNELING +
151 " INTEGER;");
152 }
153 if (oldVersion < 8)
154 {
155 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_LOCAL_ID +
156 " TEXT;");
157 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_REMOTE_ID +
158 " TEXT;");
159 }
160 if (oldVersion < 9)
161 {
162 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_UUID +
163 " TEXT;");
164 updateColumns(db);
165 }
166 if (oldVersion < 10)
167 {
168 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_EXCLUDED_SUBNETS +
169 " TEXT;");
170 }
171 if (oldVersion < 11)
172 {
173 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_INCLUDED_SUBNETS +
174 " TEXT;");
175 }
176 if (oldVersion < 12)
177 {
178 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_SELECTED_APPS +
179 " INTEGER;");
180 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_SELECTED_APPS_LIST +
181 " TEXT;");
182 }
183 }
184
185 private void updateColumns(SQLiteDatabase db)
186 {
187 db.beginTransaction();
188 try
189 {
190 db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " RENAME TO tmp_" + TABLE_VPNPROFILE + ";");
191 db.execSQL(DATABASE_CREATE);
192 StringBuilder insert = new StringBuilder("INSERT INTO " + TABLE_VPNPROFILE + " SELECT ");
193 SQLiteQueryBuilder.appendColumns(insert, ALL_COLUMNS);
194 db.execSQL(insert.append(" FROM tmp_" + TABLE_VPNPROFILE + ";").toString());
195 db.execSQL("DROP TABLE tmp_" + TABLE_VPNPROFILE + ";");
196 db.setTransactionSuccessful();
197 }
198 finally
199 {
200 db.endTransaction();
201 }
202 }
203 }
204
205 /**
206 * Construct a new VPN profile data source. The context is used to
207 * open/create the database.
208 * @param context context used to access the database
209 */
210 public VpnProfileDataSource(Context context)
211 {
212 this.mContext = context;
213 }
214
215 /**
216 * Open the VPN profile data source. The database is automatically created
217 * if it does not yet exist. If that fails an exception is thrown.
218 * @return itself (allows to chain initialization calls)
219 * @throws SQLException if the database could not be opened or created
220 */
221 public VpnProfileDataSource open() throws SQLException
222 {
223 if (mDbHelper == null)
224 {
225 mDbHelper = new DatabaseHelper(mContext);
226 mDatabase = mDbHelper.getWritableDatabase();
227 }
228 return this;
229 }
230
231 /**
232 * Close the data source.
233 */
234 public void close()
235 {
236 if (mDbHelper != null)
237 {
238 mDbHelper.close();
239 mDbHelper = null;
240 }
241 }
242
243 /**
244 * Insert the given VPN profile into the database. On success the Id of
245 * the object is updated and the object returned.
246 *
247 * @param profile the profile to add
248 * @return the added VPN profile or null, if failed
249 */
250 public VpnProfile insertProfile(VpnProfile profile)
251 {
252 ContentValues values = ContentValuesFromVpnProfile(profile);
253 long insertId = mDatabase.insert(TABLE_VPNPROFILE, null, values);
254 if (insertId == -1)
255 {
256 return null;
257 }
258 profile.setId(insertId);
259 return profile;
260 }
261
262 /**
263 * Updates the given VPN profile in the database.
264 * @param profile the profile to update
265 * @return true if update succeeded, false otherwise
266 */
267 public boolean updateVpnProfile(VpnProfile profile)
268 {
269 long id = profile.getId();
270 ContentValues values = ContentValuesFromVpnProfile(profile);
271 return mDatabase.update(TABLE_VPNPROFILE, values, KEY_ID + " = " + id, null) > 0;
272 }
273
274 /**
275 * Delete the given VPN profile from the database.
276 * @param profile the profile to delete
277 * @return true if deleted, false otherwise
278 */
279 public boolean deleteVpnProfile(VpnProfile profile)
280 {
281 long id = profile.getId();
282 return mDatabase.delete(TABLE_VPNPROFILE, KEY_ID + " = " + id, null) > 0;
283 }
284
285 /**
286 * Get a single VPN profile from the database.
287 * @param id the ID of the VPN profile
288 * @return the profile or null, if not found
289 */
290 public VpnProfile getVpnProfile(long id)
291 {
292 VpnProfile profile = null;
293 Cursor cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS,
294 KEY_ID + "=" + id, null, null, null, null);
295 if (cursor.moveToFirst())
296 {
297 profile = VpnProfileFromCursor(cursor);
298 }
299 cursor.close();
300 return profile;
301 }
302
303 /**
304 * Get a single VPN profile from the database by its UUID.
305 * @param uuid the UUID of the VPN profile
306 * @return the profile or null, if not found
307 */
308 public VpnProfile getVpnProfile(UUID uuid)
309 {
310 VpnProfile profile = null;
311 Cursor cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS,
312 KEY_UUID + "='" + uuid.toString() + "'", null, null, null, null);
313 if (cursor.moveToFirst())
314 {
315 profile = VpnProfileFromCursor(cursor);
316 }
317 cursor.close();
318 return profile;
319 }
320
321 /**
322 * Get a list of all VPN profiles stored in the database.
323 * @return list of VPN profiles
324 */
325 public List<VpnProfile> getAllVpnProfiles()
326 {
327 List<VpnProfile> vpnProfiles = new ArrayList<VpnProfile>();
328
329 Cursor cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS, null, null, null, null, null);
330 cursor.moveToFirst();
331 while (!cursor.isAfterLast())
332 {
333 VpnProfile vpnProfile = VpnProfileFromCursor(cursor);
334 vpnProfiles.add(vpnProfile);
335 cursor.moveToNext();
336 }
337 cursor.close();
338 return vpnProfiles;
339 }
340
341 private VpnProfile VpnProfileFromCursor(Cursor cursor)
342 {
343 VpnProfile profile = new VpnProfile();
344 profile.setId(cursor.getLong(cursor.getColumnIndex(KEY_ID)));
345 profile.setUUID(getUUID(cursor, cursor.getColumnIndex(KEY_UUID)));
346 profile.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
347 profile.setGateway(cursor.getString(cursor.getColumnIndex(KEY_GATEWAY)));
348 profile.setVpnType(VpnType.fromIdentifier(cursor.getString(cursor.getColumnIndex(KEY_VPN_TYPE))));
349 profile.setUsername(cursor.getString(cursor.getColumnIndex(KEY_USERNAME)));
350 profile.setPassword(cursor.getString(cursor.getColumnIndex(KEY_PASSWORD)));
351 profile.setCertificateAlias(cursor.getString(cursor.getColumnIndex(KEY_CERTIFICATE)));
352 profile.setUserCertificateAlias(cursor.getString(cursor.getColumnIndex(KEY_USER_CERTIFICATE)));
353 profile.setMTU(getInt(cursor, cursor.getColumnIndex(KEY_MTU)));
354 profile.setPort(getInt(cursor, cursor.getColumnIndex(KEY_PORT)));
355 profile.setSplitTunneling(getInt(cursor, cursor.getColumnIndex(KEY_SPLIT_TUNNELING)));
356 profile.setLocalId(cursor.getString(cursor.getColumnIndex(KEY_LOCAL_ID)));
357 profile.setRemoteId(cursor.getString(cursor.getColumnIndex(KEY_REMOTE_ID)));
358 profile.setExcludedSubnets(cursor.getString(cursor.getColumnIndex(KEY_EXCLUDED_SUBNETS)));
359 profile.setIncludedSubnets(cursor.getString(cursor.getColumnIndex(KEY_INCLUDED_SUBNETS)));
360 profile.setSelectedAppsHandling(getInt(cursor, cursor.getColumnIndex(KEY_SELECTED_APPS)));
361 profile.setSelectedApps(cursor.getString(cursor.getColumnIndex(KEY_SELECTED_APPS_LIST)));
362 return profile;
363 }
364
365 private ContentValues ContentValuesFromVpnProfile(VpnProfile profile)
366 {
367 ContentValues values = new ContentValues();
368 values.put(KEY_UUID, profile.getUUID() != null ? profile.getUUID().toString() : null);
369 values.put(KEY_NAME, profile.getName());
370 values.put(KEY_GATEWAY, profile.getGateway());
371 values.put(KEY_VPN_TYPE, profile.getVpnType().getIdentifier());
372 values.put(KEY_USERNAME, profile.getUsername());
373 values.put(KEY_PASSWORD, profile.getPassword());
374 values.put(KEY_CERTIFICATE, profile.getCertificateAlias());
375 values.put(KEY_USER_CERTIFICATE, profile.getUserCertificateAlias());
376 values.put(KEY_MTU, profile.getMTU());
377 values.put(KEY_PORT, profile.getPort());
378 values.put(KEY_SPLIT_TUNNELING, profile.getSplitTunneling());
379 values.put(KEY_LOCAL_ID, profile.getLocalId());
380 values.put(KEY_REMOTE_ID, profile.getRemoteId());
381 values.put(KEY_EXCLUDED_SUBNETS, profile.getExcludedSubnets());
382 values.put(KEY_INCLUDED_SUBNETS, profile.getIncludedSubnets());
383 values.put(KEY_SELECTED_APPS, profile.getSelectedAppsHandling().getValue());
384 values.put(KEY_SELECTED_APPS_LIST, profile.getSelectedApps());
385 return values;
386 }
387
388 private Integer getInt(Cursor cursor, int columnIndex)
389 {
390 return cursor.isNull(columnIndex) ? null : cursor.getInt(columnIndex);
391 }
392
393 private UUID getUUID(Cursor cursor, int columnIndex)
394 {
395 try
396 {
397 return cursor.isNull(columnIndex) ? null : UUID.fromString(cursor.getString(columnIndex));
398 }
399 catch (Exception e)
400 {
401 return null;
402 }
403 }
404 }