From 237a0b1805fc759693cfe2aaeffad1cbccecd08e Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 6 Feb 2017 20:56:33 +0100 Subject: [PATCH] add simple tests for KeychainExternalProvider --- .../provider/ApiDataAccessObject.java | 4 + .../remote/KeychainExternalProviderTest.java | 211 ++++++++++++++++++ .../src/test/resources/test-keys/testring.pub | Bin 0 -> 839 bytes .../src/test/resources/test-keys/testring.sec | Bin 0 -> 947 bytes 4 files changed, 215 insertions(+) create mode 100644 OpenKeychain/src/test/java/org/sufficientlysecure/keychain/remote/KeychainExternalProviderTest.java create mode 100644 OpenKeychain/src/test/resources/test-keys/testring.pub create mode 100644 OpenKeychain/src/test/resources/test-keys/testring.sec diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ApiDataAccessObject.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ApiDataAccessObject.java index 7c8295ad5..eeda44a38 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ApiDataAccessObject.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ApiDataAccessObject.java @@ -121,6 +121,10 @@ public class ApiDataAccessObject { contentValueForApiApps(appSettings)); } + public void deleteApiApp(String packageName) { + mQueryInterface.delete(ApiApps.buildByPackageNameUri(packageName), null, null); + } + public void insertApiAccount(Uri uri, AccountSettings accSettings) { mQueryInterface.insert(uri, contentValueForApiAccounts(accSettings)); } diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/remote/KeychainExternalProviderTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/remote/KeychainExternalProviderTest.java new file mode 100644 index 000000000..7628c22c1 --- /dev/null +++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/remote/KeychainExternalProviderTest.java @@ -0,0 +1,211 @@ +package org.sufficientlysecure.keychain.remote; + + +import java.security.AccessControlException; +import java.util.Collections; + +import android.content.ContentResolver; +import android.content.pm.PackageInfo; +import android.content.pm.Signature; +import android.database.Cursor; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.res.builder.RobolectricPackageManager; +import org.sufficientlysecure.keychain.KeychainTestRunner; +import org.sufficientlysecure.keychain.operations.CertifyOperation; +import org.sufficientlysecure.keychain.operations.results.CertifyResult; +import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.provider.ApiDataAccessObject; +import org.sufficientlysecure.keychain.provider.KeychainExternalContract.EmailStatus; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelperSaveTest; +import org.sufficientlysecure.keychain.service.CertifyActionsParcel; +import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.util.ProgressScaler; + +import static org.junit.Assert.*; + + +@SuppressWarnings("WeakerAccess") +@RunWith(KeychainTestRunner.class) +public class KeychainExternalProviderTest { + static final String PACKAGE_NAME = "test.package"; + static final byte[] PACKAGE_SIGNATURE = new byte[] { 1, 2, 3 }; + static final String MAIL_ADDRESS_1 = "twi@openkeychain.org"; + static final String MAIL_ADDRESS_2 = "pink@openkeychain.org"; + static final String MAIL_ADDRESS_SEC_1 = "twi-sec@openkeychain.org"; + static final String USER_ID_1 = "twi "; + static final String USER_ID_SEC_1 = "twi "; + static final long KEY_ID_SECRET = 0x5D4DA4423C39122FL; + static final long KEY_ID_PUBLIC = 0x9A282CE2AB44A382L; + + + ProviderHelper providerHelper = new ProviderHelper(RuntimeEnvironment.application); + ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver(); + ApiPermissionHelper apiPermissionHelper; + ApiDataAccessObject apiDao; + + + @Before + public void setUp() throws Exception { + RobolectricPackageManager rpm = (RobolectricPackageManager) RuntimeEnvironment.getPackageManager(); + rpm.setPackagesForUid(0, PACKAGE_NAME); + PackageInfo packageInfo = new PackageInfo(); + packageInfo.signatures = new Signature[] { new Signature(PACKAGE_SIGNATURE) }; + packageInfo.packageName = PACKAGE_NAME; + rpm.addPackage(packageInfo); + + apiDao = new ApiDataAccessObject(RuntimeEnvironment.application); + apiPermissionHelper = new ApiPermissionHelper(RuntimeEnvironment.application, apiDao); + + apiDao.insertApiApp(new AppSettings(PACKAGE_NAME, PACKAGE_SIGNATURE)); + } + + @Test(expected = AccessControlException.class) + public void testPermission__withMissingPackage() throws Exception { + apiDao.deleteApiApp(PACKAGE_NAME); + + contentResolver.query( + EmailStatus.CONTENT_URI, + new String[] { EmailStatus.EMAIL_ADDRESS, EmailStatus.EMAIL_ADDRESS, EmailStatus.USER_ID }, + null, new String [] { }, null + ); + } + + @Test(expected = AccessControlException.class) + public void testPermission__withWrongPackageCert() throws Exception { + apiDao.deleteApiApp(PACKAGE_NAME); + apiDao.insertApiApp(new AppSettings(PACKAGE_NAME, new byte[] { 1, 2, 4 })); + + contentResolver.query( + EmailStatus.CONTENT_URI, + new String[] { EmailStatus.EMAIL_ADDRESS, EmailStatus.EMAIL_ADDRESS, EmailStatus.USER_ID }, + null, new String [] { }, null + ); + } + + @Test + public void testQuery__withNonExistentAddress() throws Exception { + Cursor cursor = contentResolver.query( + EmailStatus.CONTENT_URI, new String[] { + EmailStatus.EMAIL_ADDRESS, EmailStatus.EMAIL_STATUS, EmailStatus.USER_ID }, + null, new String [] { MAIL_ADDRESS_1 }, null + ); + + assertNotNull(cursor); + assertTrue(cursor.moveToFirst()); + assertEquals(MAIL_ADDRESS_1, cursor.getString(0)); + assertEquals(0, cursor.getInt(1)); + assertTrue(cursor.isNull(2)); + } + + @Test + public void testQuery() throws Exception { + insertPublicKeyringFrom("/test-keys/testring.pub"); + + Cursor cursor = contentResolver.query( + EmailStatus.CONTENT_URI, new String[] { + EmailStatus.EMAIL_ADDRESS, EmailStatus.EMAIL_STATUS, EmailStatus.USER_ID }, + null, new String [] { MAIL_ADDRESS_1 }, null + ); + + assertNotNull(cursor); + assertTrue(cursor.moveToFirst()); + assertEquals(MAIL_ADDRESS_1, cursor.getString(0)); + assertEquals(1, cursor.getInt(1)); + assertEquals("twi ", cursor.getString(2)); + assertFalse(cursor.moveToNext()); + } + + @Test + public void testQuery__multiple() throws Exception { + insertPublicKeyringFrom("/test-keys/testring.pub"); + + Cursor cursor = contentResolver.query( + EmailStatus.CONTENT_URI, new String[] { + EmailStatus.EMAIL_ADDRESS, EmailStatus.EMAIL_STATUS, EmailStatus.USER_ID }, + null, new String [] { MAIL_ADDRESS_1, MAIL_ADDRESS_2 }, null + ); + + assertNotNull(cursor); + assertTrue(cursor.moveToNext()); + assertEquals(MAIL_ADDRESS_2, cursor.getString(0)); + assertEquals(0, cursor.getInt(1)); + assertTrue(cursor.isNull(2)); + assertTrue(cursor.moveToNext()); + assertEquals(MAIL_ADDRESS_1, cursor.getString(0)); + assertEquals(1, cursor.getInt(1)); + assertEquals("twi ", cursor.getString(2)); + assertFalse(cursor.moveToNext()); + } + + @Test + public void testQuery__withSecretKey() throws Exception { + insertSecretKeyringFrom("/test-keys/testring.sec"); + + Cursor cursor = contentResolver.query( + EmailStatus.CONTENT_URI, new String[] { + EmailStatus.EMAIL_ADDRESS, EmailStatus.EMAIL_STATUS, EmailStatus.USER_ID }, + null, new String [] { MAIL_ADDRESS_SEC_1 }, null + ); + + assertNotNull(cursor); + assertTrue(cursor.moveToFirst()); + assertEquals(MAIL_ADDRESS_SEC_1, cursor.getString(0)); + assertEquals(USER_ID_SEC_1, cursor.getString(2)); + assertEquals(2, cursor.getInt(1)); + assertFalse(cursor.moveToNext()); + } + + @Test + public void testQuery__withConfirmedKey() throws Exception { + insertSecretKeyringFrom("/test-keys/testring.sec"); + insertPublicKeyringFrom("/test-keys/testring.pub"); + + certifyKey(KEY_ID_SECRET, KEY_ID_PUBLIC, USER_ID_1); + + Cursor cursor = contentResolver.query( + EmailStatus.CONTENT_URI, new String[] { + EmailStatus.EMAIL_ADDRESS, EmailStatus.EMAIL_STATUS, EmailStatus.USER_ID }, + null, new String [] { MAIL_ADDRESS_1 }, null + ); + + assertNotNull(cursor); + assertTrue(cursor.moveToFirst()); + assertEquals(MAIL_ADDRESS_1, cursor.getString(0)); + assertEquals(USER_ID_1, cursor.getString(2)); + assertEquals(2, cursor.getInt(1)); + assertFalse(cursor.moveToNext()); + } + + private void certifyKey(long secretMasterKeyId, long publicMasterKeyId, String userId) { + CertifyActionsParcel certifyActionsParcel = new CertifyActionsParcel(secretMasterKeyId); + certifyActionsParcel.add(new CertifyAction(publicMasterKeyId, Collections.singletonList(userId), null)); + CertifyOperation op = new CertifyOperation( + RuntimeEnvironment.application, providerHelper, new ProgressScaler(), null); + CertifyResult certifyResult = op.execute(certifyActionsParcel, new CryptoInputParcel()); + + assertTrue(certifyResult.success()); + } + + private void insertPublicKeyringFrom(String filename) throws Exception { + UncachedKeyRing ring = readRingFromResource(filename); + SaveKeyringResult saveKeyringResult = providerHelper.savePublicKeyRing(ring); + assertTrue(saveKeyringResult.success()); + } + + private void insertSecretKeyringFrom(String filename) throws Exception { + UncachedKeyRing ring = readRingFromResource(filename); + SaveKeyringResult saveKeyringResult = providerHelper.saveSecretKeyRing(ring, new ProgressScaler()); + assertTrue(saveKeyringResult.success()); + } + + UncachedKeyRing readRingFromResource(String name) throws Exception { + return UncachedKeyRing.fromStream(ProviderHelperSaveTest.class.getResourceAsStream(name)).next(); + } +} \ No newline at end of file diff --git a/OpenKeychain/src/test/resources/test-keys/testring.pub b/OpenKeychain/src/test/resources/test-keys/testring.pub new file mode 100644 index 0000000000000000000000000000000000000000..8c401e50baf3d58d2f1eff54571e08526587cd7d GIT binary patch literal 839 zcmbOc#1b)M{uW^ltu~Kyw#9Iwsq&!o>21q#M7o_H8 zr&cCsBxdI6&=@jBG{C7FHF_823 z8%wq;%giP-7dHHfH#l2-dWq`A_sPZo)Xq0c~AY3*!4RtNQI;yFH4T+)?Qav!&%v?q7fA>F*;Y zEBr$yGnFlfUw2VN@v32&^9lPfmtFbm+|6!Ja&MbA&J@++y5E{ohKdTD<1pL*TA&x{N|`M$-fbQWdA zX|!#qjZX|>Jt}r<$|~m>k8g2bm-Kwg$nZZb`!d<-4Yrg-8$Dsv!wjC zo7U;eeG}&Ot_y#6X=nEtd*8Ou4sZD-r~PgoZV`U0!pz9Q-jRqJG%UzTtYk4G!#jVA z&5K25yqjL2{vt2nM6>p0t)8dbb_R1xGOa7D+Eu{FaIyYTpEvVi?Z#;@ST&sPZ1iWD TI^}tL$YdGtu~Kyw#v{1%PG+vPjD5Fmt7KbF z*u0$Q{EC{W-1h6nJTjBdF{B$uq-}WE;kbVOuf?vxYWyp&dW&!UykV|Eue1I8;Af_H z)?5$Mh+I9_LMYS5H!owgNz;z*)r?!@O3E`8Y=DGracZ(denDzpc4}pEMq*~3UVc%! zT}Kg%urL>c6bm;e2RoA}7n2wxlOzLc6Uc8&^B9?CGcs^-3dH&@ak8-#(r2h;_#d_M zK^M2tr%sVforlp{d`+g;j*HlDx*qBAp>g4}rJdFc|I9W`vRP7J7^qhwUEVcwVZz4M zeqVhi7M__O&8WS4`FhVeSc1+zN@)4Xo2{u_KF@DVoVReL=%N)FwasUp-!6V|)+W8- z+`YxJzhwEhTu8KVZ`^;HH6`=PO6ijKhYgBb&)om*vaS#%=w7-7?@Cy+Vlnrwqv271 zg(M%`w=R0nuIKk;nVjG)C5<&(dNzpH>mKh9oLb|1`-~`m{bcf!(kw;5f82-oEJJc#xtr9QvO@Fk2iI4oZmtQl?pU2I$Nn1B`?Hd2!Cr{2WJuTKRYtSzL zZOzEA(Nb%jDQ9nRsGPnO4r5Kk3O~waXgfif2NfIk4aM{}O&Nc#)Pm z=fanF7Oc`R=d4jqt-AWc{y0~db7u3yPx+>|=7;h&&o{oMzPck3HMCif)7@=5MurwP z?#8veAx9rttlc;7k!u&9t?s%))@MgDZ!i9P+vwE~hX3{7)$T6M{C+D^p)WN`?a3au U9XFE;4&Awy-?MB>(bcLX0NLoDrvLx| literal 0 HcmV?d00001