From 0b181743a3d6b1423e112b17a400b5ac4ac09bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 20 Sep 2015 22:42:50 +0200 Subject: Keyservers: Dont follow redirects, pin pgp.mit.edu, check for pinned cert on add (OKC-01-018) --- .../assets/hkps.pool.sks-keyservers.net.CA.cer | 32 +++++++++ OpenKeychain/src/main/assets/pgp.mit.edu.cer | 33 +++++++++ .../src/main/assets/sks-keyservers.netCA.cer | 32 --------- .../keychain/KeychainApplication.java | 5 +- .../keychain/keyimport/HkpKeyserver.java | 6 +- .../keychain/ui/SettingsKeyserverFragment.java | 22 +----- .../ui/dialog/AddEditKeyserverDialogFragment.java | 80 +++++++++++++++++---- .../keychain/util/TlsHelper.java | 82 +++++++--------------- .../src/main/res/layout/add_keyserver_dialog.xml | 36 +++++++--- OpenKeychain/src/main/res/values-cs/strings.xml | 4 +- OpenKeychain/src/main/res/values-de/strings.xml | 6 +- OpenKeychain/src/main/res/values-es/strings.xml | 6 +- OpenKeychain/src/main/res/values-eu/strings.xml | 6 +- OpenKeychain/src/main/res/values-fa/strings.xml | 2 +- OpenKeychain/src/main/res/values-fr/strings.xml | 6 +- OpenKeychain/src/main/res/values-it/strings.xml | 2 +- OpenKeychain/src/main/res/values-ja/strings.xml | 6 +- OpenKeychain/src/main/res/values-nl/strings.xml | 6 +- OpenKeychain/src/main/res/values-ru/strings.xml | 6 +- OpenKeychain/src/main/res/values-sr/strings.xml | 6 +- OpenKeychain/src/main/res/values-sv/strings.xml | 6 +- .../src/main/res/values-zh-rTW/strings.xml | 6 +- OpenKeychain/src/main/res/values/strings.xml | 10 +-- 23 files changed, 232 insertions(+), 174 deletions(-) create mode 100644 OpenKeychain/src/main/assets/hkps.pool.sks-keyservers.net.CA.cer create mode 100644 OpenKeychain/src/main/assets/pgp.mit.edu.cer delete mode 100644 OpenKeychain/src/main/assets/sks-keyservers.netCA.cer (limited to 'OpenKeychain/src') diff --git a/OpenKeychain/src/main/assets/hkps.pool.sks-keyservers.net.CA.cer b/OpenKeychain/src/main/assets/hkps.pool.sks-keyservers.net.CA.cer new file mode 100644 index 000000000..24a2ad2e8 --- /dev/null +++ b/OpenKeychain/src/main/assets/hkps.pool.sks-keyservers.net.CA.cer @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFizCCA3OgAwIBAgIJAK9zyLTPn4CPMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV +BAYTAk5PMQ0wCwYDVQQIDARPc2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5u +ZXQgQ0ExHjAcBgNVBAMMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTAeFw0xMjEwMDkw +MDMzMzdaFw0yMjEwMDcwMDMzMzdaMFwxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARP +c2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5uZXQgQ0ExHjAcBgNVBAMMFXNr +cy1rZXlzZXJ2ZXJzLm5ldCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBANdsWy4PXWNUCkS3L//nrd0GqN3dVwoBGZ6w94Tw2jPDPifegwxQozFXkG6I +6A4TK1CJLXPvfz0UP0aBYyPmTNadDinaB9T4jIwd4rnxl+59GiEmqkN3IfPsv5Jj +MkKUmJnvOT0DEVlEaO1UZIwx5WpfprB3mR81/qm4XkAgmYrmgnLXd/pJDAMk7y1F +45b5zWofiD5l677lplcIPRbFhpJ6kDTODXh/XEdtF71EAeaOdEGOvyGDmCO0GWqS +FDkMMPTlieLA/0rgFTcz4xwUYj/cD5e0ZBuSkYsYFAU3hd1cGfBue0cPZaQH2HYx +Qk4zXD8S3F4690fRhr+tki5gyG6JDR67aKp3BIGLqm7f45WkX1hYp+YXywmEziM4 +aSbGYhx8hoFGfq9UcfPEvp2aoc8u5sdqjDslhyUzM1v3m3ZGbhwEOnVjljY6JJLx +MxagxnZZSAY424ZZ3t71E/Mn27dm2w+xFRuoy8JEjv1d+BT3eChM5KaNwrj0IO/y +u8kFIgWYA1vZ/15qMT+tyJTfyrNVV/7Df7TNeWyNqjJ5rBmt0M6NpHG7CrUSkBy9 +p8JhimgjP5r0FlEkgg+lyD+V79H98gQfVgP3pbJICz0SpBQf2F/2tyS4rLm+49rP +fcOajiXEuyhpcmzgusAj/1FjrtlynH1r9mnNaX4e+rLWzvU5AgMBAAGjUDBOMB0G +A1UdDgQWBBTkwyoJFGfYTVISTpM8E+igjdq28zAfBgNVHSMEGDAWgBTkwyoJFGfY +TVISTpM8E+igjdq28zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAR +OXnYwu3g1ZjHyley3fZI5aLPsaE17cOImVTehC8DcIphm2HOMR/hYTTL+V0G4P+u +gH+6xeRLKSHMHZTtSBIa6GDL03434y9CBuwGvAFCMU2GV8w92/Z7apkAhdLToZA/ +X/iWP2jeaVJhxgEcH8uPrnSlqoPBcKC9PrgUzQYfSZJkLmB+3jEa3HKruy1abJP5 +gAdQvwvcPpvYRnIzUc9fZODsVmlHVFBCl2dlu/iHh2h4GmL4Da2rRkUMlbVTdioB +UYIvMycdOkpH5wJftzw7cpjsudGas0PARDXCFfGyKhwBRFY7Xp7lbjtU5Rz0Gc04 +lPrhDf0pFE98Aw4jJRpFeWMjpXUEaG1cq7D641RpgcMfPFvOHY47rvDTS7XJOaUT +BwRjmDt896s6vMDcaG/uXJbQjuzmmx3W2Idyh3s5SI0GTHb0IwMKYb4eBUIpQOnB +cE77VnCYqKvN1NVYAqhWjXbY7XasZvszCRcOG+W3FqNaHOK/n/0ueb0uijdLan+U +f4p1bjbAox8eAOQS/8a3bzkJzdyBNUKGx1BIK2IBL9bn/HravSDOiNRSnZ/R3l9G +ZauX0tu7IIDlRCILXSyeazu0aj/vdT3YFQXPcvt5Fkf5wiNTo53f72/jYEJd6qph +WrpoKqrwGwTpRUCMhYIUt65hsTxCiJJ5nKe39h46sg== +-----END CERTIFICATE----- diff --git a/OpenKeychain/src/main/assets/pgp.mit.edu.cer b/OpenKeychain/src/main/assets/pgp.mit.edu.cer new file mode 100644 index 000000000..7249b3611 --- /dev/null +++ b/OpenKeychain/src/main/assets/pgp.mit.edu.cer @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFpzCCBI+gAwIBAgIQSCQjuTbnogvWCWWHeCDMbzANBgkqhkiG9w0BAQsFADB2 +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCTUkxEjAQBgNVBAcTCUFubiBBcmJvcjES +MBAGA1UEChMJSW50ZXJuZXQyMREwDwYDVQQLEwhJbkNvbW1vbjEfMB0GA1UEAxMW +SW5Db21tb24gUlNBIFNlcnZlciBDQTAeFw0xNDEwMDkwMDAwMDBaFw0xNzEwMDgy +MzU5NTlaMIHlMQswCQYDVQQGEwJVUzEOMAwGA1UEERMFMDIxMzkxCzAJBgNVBAgT +Ak1hMRIwEAYDVQQHEwlDYW1icmlkZ2UxHTAbBgNVBAkTFDc3IE1hc3NhY2h1c2V0 +dHMgQXZlMS4wLAYDVQQKEyVNYXNzYWNodXNldHRzIEluc3RpdHV0ZSBvZiBUZWNo +bm9sb2d5MSowKAYDVQQLFCFJbmZvcm1hdGlvbiBTZXJ2aWNlcyAmIFRlY2hub2xv +Z3kxFDASBgNVBAsTC1BsYXRpbnVtU1NMMRQwEgYDVQQDEwtwZ3AubWl0LmVkdTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOXCQWXwK1O/saHfUEJjeE6w +VvTMe8xgl5qmkU+9U2TS6HdyVItD9fHZ3sAwVHo7mYtLGXp0S8F2hiiyLgQeQo84 +F/owinPaPU8c+2Ogw464HbROmjU7Vc/iHQklA0kR+lZsFwZuWd+nYjmPrNfm87Ik +k9Wenco7wwFUquoJ8XZW1RVTr9WRWWlyNKwPnil5aBUGtbG6CP1+IFN75xfJYjz5 +g+JcLHYsKyb6JhPYxT42ZdgTPKVRJNuIpyOMXMIPB/qFgUyU+2T/g7vxoa3THllq +vkp/ds5lpDe+uu6H9mbtMYvX5w9TBqt7YPegWcTUhGERnytXxeNpncYkzGMMUN0C +AwEAAaOCAb8wggG7MB8GA1UdIwQYMBaAFB4Fo3ePbJbiW4dLprSGrHEADOc4MB0G +A1UdDgQWBBRISoMA6cVQE5089wT6LFO4aiNnzTAOBgNVHQ8BAf8EBAMCBaAwDAYD +VR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwZwYDVR0g +BGAwXjBSBgwrBgEEAa4jAQQDAQEwQjBABggrBgEFBQcCARY0aHR0cHM6Ly93d3cu +aW5jb21tb24ub3JnL2NlcnQvcmVwb3NpdG9yeS9jcHNfc3NsLnBkZjAIBgZngQwB +AgIwRAYDVR0fBD0wOzA5oDegNYYzaHR0cDovL2NybC5pbmNvbW1vbi1yc2Eub3Jn +L0luQ29tbW9uUlNBU2VydmVyQ0EuY3JsMHUGCCsGAQUFBwEBBGkwZzA+BggrBgEF +BQcwAoYyaHR0cDovL2NydC51c2VydHJ1c3QuY29tL0luQ29tbW9uUlNBU2VydmVy +Q0FfMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20w +FgYDVR0RBA8wDYILcGdwLm1pdC5lZHUwDQYJKoZIhvcNAQELBQADggEBAHbQqv2o +LrRD8rMzaHvPHVa92gfi6bpEsiRsVw3kpH4D4k+PL9LWkgtgTWpM+MvskiUvS9ay +FbWdXiy/peOj421fwnL/re9gmWs1g7FtUrDgIpz2T2jonPqbnIJPMHxI+ICWZMYH +V/dO844geRKAiGs/UZbG4Uf1Jo0PxtPtD5puaUk4l9Va8WHU2OLq0kzS9K+iu/sx +z0XG+fAMneyiXm5jtfjYE2W8/h61RhZulSUmYBkiMLzKr5eqe2VIkMqyTfyZ5zms +1LZ1GWaouMsTBN1+2TXssQ71L1tIZg/lXJVlfVRkwOIV5Mp3ohxLSBZT8qNSef1v +mFNa+DGU1sdl6m4= +-----END CERTIFICATE----- diff --git a/OpenKeychain/src/main/assets/sks-keyservers.netCA.cer b/OpenKeychain/src/main/assets/sks-keyservers.netCA.cer deleted file mode 100644 index 24a2ad2e8..000000000 --- a/OpenKeychain/src/main/assets/sks-keyservers.netCA.cer +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFizCCA3OgAwIBAgIJAK9zyLTPn4CPMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV -BAYTAk5PMQ0wCwYDVQQIDARPc2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5u -ZXQgQ0ExHjAcBgNVBAMMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTAeFw0xMjEwMDkw -MDMzMzdaFw0yMjEwMDcwMDMzMzdaMFwxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARP -c2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5uZXQgQ0ExHjAcBgNVBAMMFXNr -cy1rZXlzZXJ2ZXJzLm5ldCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBANdsWy4PXWNUCkS3L//nrd0GqN3dVwoBGZ6w94Tw2jPDPifegwxQozFXkG6I -6A4TK1CJLXPvfz0UP0aBYyPmTNadDinaB9T4jIwd4rnxl+59GiEmqkN3IfPsv5Jj -MkKUmJnvOT0DEVlEaO1UZIwx5WpfprB3mR81/qm4XkAgmYrmgnLXd/pJDAMk7y1F -45b5zWofiD5l677lplcIPRbFhpJ6kDTODXh/XEdtF71EAeaOdEGOvyGDmCO0GWqS -FDkMMPTlieLA/0rgFTcz4xwUYj/cD5e0ZBuSkYsYFAU3hd1cGfBue0cPZaQH2HYx -Qk4zXD8S3F4690fRhr+tki5gyG6JDR67aKp3BIGLqm7f45WkX1hYp+YXywmEziM4 -aSbGYhx8hoFGfq9UcfPEvp2aoc8u5sdqjDslhyUzM1v3m3ZGbhwEOnVjljY6JJLx -MxagxnZZSAY424ZZ3t71E/Mn27dm2w+xFRuoy8JEjv1d+BT3eChM5KaNwrj0IO/y -u8kFIgWYA1vZ/15qMT+tyJTfyrNVV/7Df7TNeWyNqjJ5rBmt0M6NpHG7CrUSkBy9 -p8JhimgjP5r0FlEkgg+lyD+V79H98gQfVgP3pbJICz0SpBQf2F/2tyS4rLm+49rP -fcOajiXEuyhpcmzgusAj/1FjrtlynH1r9mnNaX4e+rLWzvU5AgMBAAGjUDBOMB0G -A1UdDgQWBBTkwyoJFGfYTVISTpM8E+igjdq28zAfBgNVHSMEGDAWgBTkwyoJFGfY -TVISTpM8E+igjdq28zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAR -OXnYwu3g1ZjHyley3fZI5aLPsaE17cOImVTehC8DcIphm2HOMR/hYTTL+V0G4P+u -gH+6xeRLKSHMHZTtSBIa6GDL03434y9CBuwGvAFCMU2GV8w92/Z7apkAhdLToZA/ -X/iWP2jeaVJhxgEcH8uPrnSlqoPBcKC9PrgUzQYfSZJkLmB+3jEa3HKruy1abJP5 -gAdQvwvcPpvYRnIzUc9fZODsVmlHVFBCl2dlu/iHh2h4GmL4Da2rRkUMlbVTdioB -UYIvMycdOkpH5wJftzw7cpjsudGas0PARDXCFfGyKhwBRFY7Xp7lbjtU5Rz0Gc04 -lPrhDf0pFE98Aw4jJRpFeWMjpXUEaG1cq7D641RpgcMfPFvOHY47rvDTS7XJOaUT -BwRjmDt896s6vMDcaG/uXJbQjuzmmx3W2Idyh3s5SI0GTHb0IwMKYb4eBUIpQOnB -cE77VnCYqKvN1NVYAqhWjXbY7XasZvszCRcOG+W3FqNaHOK/n/0ueb0uijdLan+U -f4p1bjbAox8eAOQS/8a3bzkJzdyBNUKGx1BIK2IBL9bn/HravSDOiNRSnZ/R3l9G -ZauX0tu7IIDlRCILXSyeazu0aj/vdT3YFQXPcvt5Fkf5wiNTo53f72/jYEJd6qph -WrpoKqrwGwTpRUCMhYIUt65hsTxCiJJ5nKe39h46sg== ------END CERTIFICATE----- diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index 311ef2d3b..45d81749a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -91,14 +91,15 @@ public class KeychainApplication extends Application { } brandGlowEffect(getApplicationContext(), - FormattingUtils.getColorFromAttr(getApplicationContext(), R.attr.colorPrimary)); + FormattingUtils.getColorFromAttr(getApplicationContext(), R.attr.colorPrimary)); setupAccountAsNeeded(this); // Update keyserver list as needed Preferences.getPreferences(this).upgradePreferences(this); - TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer"); + TlsHelper.addPinnedCertificate("hkps.pool.sks-keyservers.net", getAssets(), "hkps.pool.sks-keyservers.net.CA.cer"); + TlsHelper.addPinnedCertificate("pgp.mit.edu", getAssets(), "pgp.mit.edu.cer"); TemporaryStorageProvider.cleanUp(this); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index 558b8ce7d..5683decdf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -204,11 +204,15 @@ public class HkpKeyserver extends Keyserver { OkHttpClient client = new OkHttpClient(); try { - TlsHelper.pinCertificateIfNecessary(client, url); + TlsHelper.usePinnedCertificateIfAvailable(client, url); } catch (TlsHelper.TlsHelperException e) { Log.w(Constants.TAG, e); } + // don't follow any redirects + client.setFollowRedirects(false); + client.setFollowSslRedirects(false); + if (proxy != null) { client.setProxy(proxy); client.setConnectTimeout(30000, TimeUnit.MILLISECONDS); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java index d8edbe4f8..5a8ab36bc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyserverFragment.java @@ -155,7 +155,7 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC data.getBoolean(AddEditKeyserverDialogFragment.MESSAGE_VERIFIED); if (verified) { Notify.create(getActivity(), - R.string.add_keyserver_verified, Notify.Style.OK).show(); + R.string.add_keyserver_connection_verified, Notify.Style.OK).show(); } else { Notify.create(getActivity(), R.string.add_keyserver_without_verification, @@ -177,26 +177,6 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC } break; } - case AddEditKeyserverDialogFragment.MESSAGE_VERIFICATION_FAILED: { - AddEditKeyserverDialogFragment.FailureReason failureReason = - (AddEditKeyserverDialogFragment.FailureReason) data.getSerializable( - AddEditKeyserverDialogFragment.MESSAGE_FAILURE_REASON); - switch (failureReason) { - case CONNECTION_FAILED: { - Notify.create(getActivity(), - R.string.add_keyserver_connection_failed, - Notify.Style.ERROR).show(); - break; - } - case INVALID_URL: { - Notify.create(getActivity(), - R.string.add_keyserver_invalid_url, - Notify.Style.ERROR).show(); - break; - } - } - break; - } } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java index 47bc7dfda..3d96f3c6d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java @@ -24,6 +24,7 @@ import java.net.URI; import java.net.URISyntaxException; import android.app.Activity; +import android.support.design.widget.TextInputLayout; import android.support.v7.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; @@ -44,6 +45,7 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.EditText; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; @@ -54,6 +56,7 @@ import com.squareup.okhttp.Request; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; +import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.TlsHelper; @@ -68,11 +71,9 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On private static final String ARG_KEYSERVER = "arg_keyserver"; public static final int MESSAGE_OKAY = 1; - public static final int MESSAGE_VERIFICATION_FAILED = 2; public static final String MESSAGE_KEYSERVER = "new_keyserver"; public static final String MESSAGE_VERIFIED = "verified"; - public static final String MESSAGE_FAILURE_REASON = "failure_reason"; public static final String MESSAGE_KEYSERVER_DELETED = "keyserver_deleted"; public static final String MESSAGE_DIALOG_ACTION = "message_dialog_action"; public static final String MESSAGE_EDIT_POSITION = "keyserver_edited_position"; @@ -82,7 +83,9 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On private int mPosition; private EditText mKeyserverEditText; + private TextInputLayout mKeyserverEditTextLayout; private CheckBox mVerifyKeyserverCheckBox; + private CheckBox mOnlyTrustedKeyserverCheckBox; public enum DialogAction { ADD, @@ -91,7 +94,8 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On public enum FailureReason { INVALID_URL, - CONNECTION_FAILED + CONNECTION_FAILED, + NO_PINNED_CERTIFICATE } public static AddEditKeyserverDialogFragment newInstance(Messenger messenger, @@ -126,7 +130,15 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On alert.setView(view); mKeyserverEditText = (EditText) view.findViewById(R.id.keyserver_url_edit_text); - mVerifyKeyserverCheckBox = (CheckBox) view.findViewById(R.id.verify_keyserver_checkbox); + mKeyserverEditTextLayout = (TextInputLayout) view.findViewById(R.id.keyserver_url_edit_text_layout); + mVerifyKeyserverCheckBox = (CheckBox) view.findViewById(R.id.verify_connection_checkbox); + mOnlyTrustedKeyserverCheckBox = (CheckBox) view.findViewById(R.id.only_trusted_keyserver_checkbox); + mVerifyKeyserverCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mOnlyTrustedKeyserverCheckBox.setEnabled(isChecked); + } + }); switch (mDialogAction) { case ADD: { @@ -212,6 +224,8 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On positiveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + mKeyserverEditTextLayout.setErrorEnabled(false); + // behaviour same for edit and add final String keyserverUrl = mKeyserverEditText.getText().toString(); if (mVerifyKeyserverCheckBox.isChecked()) { @@ -220,13 +234,20 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() { @Override public void onOrbotStarted() { - verifyConnection(keyserverUrl, - proxyPrefs.parcelableProxy.getProxy()); + verifyConnection( + keyserverUrl, + proxyPrefs.parcelableProxy.getProxy(), + mOnlyTrustedKeyserverCheckBox.isChecked() + ); } @Override public void onNeutralButton() { - verifyConnection(keyserverUrl, null); + verifyConnection( + keyserverUrl, + null, + mOnlyTrustedKeyserverCheckBox.isChecked() + ); } @Override @@ -236,7 +257,11 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On }; if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) { - verifyConnection(keyserverUrl, proxyPrefs.parcelableProxy.getProxy()); + verifyConnection( + keyserverUrl, + proxyPrefs.parcelableProxy.getProxy(), + mOnlyTrustedKeyserverCheckBox.isChecked() + ); } } else { dismiss(); @@ -272,14 +297,28 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On sendMessageToHandler(MESSAGE_OKAY, data); } - public void verificationFailed(FailureReason reason) { - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_FAILURE_REASON, reason); + public void verificationFailed(FailureReason failureReason) { + switch (failureReason) { + case CONNECTION_FAILED: { + mKeyserverEditTextLayout.setError( + getString(R.string.add_keyserver_connection_failed)); + break; + } + case INVALID_URL: { + mKeyserverEditTextLayout.setError( + getString(R.string.add_keyserver_invalid_url)); + break; + } + case NO_PINNED_CERTIFICATE: { + mKeyserverEditTextLayout.setError( + getString(R.string.add_keyserver_keyserver_not_trusted)); + break; + } + } - sendMessageToHandler(MESSAGE_VERIFICATION_FAILED, data); } - public void verifyConnection(String keyserver, final Proxy proxy) { + public void verifyConnection(String keyserver, final Proxy proxy, final boolean onlyTrustedKeyserver) { new AsyncTask() { ProgressDialog mProgressDialog; @@ -288,7 +327,7 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On @Override protected void onPreExecute() { mProgressDialog = new ProgressDialog(getActivity()); - mProgressDialog.setMessage(getString(R.string.progress_verifying_keyserver_url)); + mProgressDialog.setMessage(getString(R.string.progress_verifying_keyserver_connection)); mProgressDialog.setCancelable(false); mProgressDialog.show(); } @@ -316,7 +355,18 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On Log.d("Converted URL", newKeyserver.toString()); OkHttpClient client = HkpKeyserver.getClient(newKeyserver.toURL(), proxy); - TlsHelper.pinCertificateIfNecessary(client, newKeyserver.toURL()); + + // don't follow any redirects + client.setFollowRedirects(false); + client.setFollowSslRedirects(false); + + if (onlyTrustedKeyserver + && !TlsHelper.usePinnedCertificateIfAvailable(client, newKeyserver.toURL())) { + Log.w(Constants.TAG, "No pinned certificate for this host in OpenKeychain's assets."); + reason = FailureReason.NO_PINNED_CERTIFICATE; + return reason; + } + client.newCall(new Request.Builder().url(newKeyserver.toURL()).build()).execute(); } catch (TlsHelper.TlsHelperException e) { reason = FailureReason.CONNECTION_FAILED; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java index d1d1ada2a..1492abdeb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Dominik Schürmann + * Copyright (C) 2013-2015 Dominik Schürmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.util; import android.content.res.AssetManager; import com.squareup.okhttp.OkHttpClient; + import org.sufficientlysecure.keychain.Constants; import java.io.ByteArrayInputStream; @@ -37,7 +38,6 @@ import java.security.cert.CertificateFactory; import java.util.HashMap; import java.util.Map; -import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; @@ -49,15 +49,14 @@ public class TlsHelper { } } - private static Map sStaticCA = new HashMap<>(); - - public static void addStaticCA(String domain, byte[] certificate) { - sStaticCA.put(domain, certificate); - } + private static Map sPinnedCertificates = new HashMap<>(); - public static void addStaticCA(String domain, AssetManager assetManager, String name) { + /** + * Add certificate from assets to pinned certificate map. + */ + public static void addPinnedCertificate(String host, AssetManager assetManager, String cerFilename) { try { - InputStream is = assetManager.open(name); + InputStream is = assetManager.open(cerFilename); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int reads = is.read(); @@ -68,27 +67,36 @@ public class TlsHelper { is.close(); - addStaticCA(domain, baos.toByteArray()); + sPinnedCertificates.put(host, baos.toByteArray()); } catch (IOException e) { Log.w(Constants.TAG, e); } } - public static void pinCertificateIfNecessary(OkHttpClient client, URL url) throws TlsHelperException, IOException { + /** + * Use pinned certificate for OkHttpClient if we have one. + * + * @return true, if certificate is available, false if not + * @throws TlsHelperException + * @throws IOException + */ + public static boolean usePinnedCertificateIfAvailable(OkHttpClient client, URL url) throws TlsHelperException, IOException { if (url.getProtocol().equals("https")) { - for (String domain : sStaticCA.keySet()) { - if (url.getHost().endsWith(domain)) { - pinCertificate(sStaticCA.get(domain), client); + // use certificate PIN from assets if we have one + for (String host : sPinnedCertificates.keySet()) { + if (url.getHost().endsWith(host)) { + pinCertificate(sPinnedCertificates.get(host), client); + return true; } } } + return false; } /** * Modifies the client to accept only requests with a given certificate. Applies to all URLs requested by the * client. * Therefore a client that is pinned this way should be used to only make requests to URLs with passed certificate. - * TODO: Refactor - More like SSH StrictHostKeyChecking than pinning? * * @param certificate certificate to pin * @param client OkHttpClient to enforce pinning on @@ -97,8 +105,10 @@ public class TlsHelper { */ private static void pinCertificate(byte[] certificate, OkHttpClient client) throws TlsHelperException, IOException { - // We don't use OkHttp's CertificatePinner since it depends on a TrustManager to verify it too. Refer to - // note at end of description: http://square.github.io/okhttp/javadoc/com/squareup/okhttp/CertificatePinner.html + // We don't use OkHttp's CertificatePinner since it can not be used to pin self-signed + // certificate if such certificate is not accepted by TrustManager. + // (Refer to note at end of description: + // http://square.github.io/okhttp/javadoc/com/squareup/okhttp/CertificatePinner.html ) // Creating our own TrustManager that trusts only our certificate eliminates the need for certificate pinning try { // Load CA @@ -126,42 +136,4 @@ public class TlsHelper { } } - /** - * Opens a Connection that will only accept certificates signed with a specific CA and skips common name check. - * This is required for some distributed Keyserver networks like sks-keyservers.net - * - * @param certificate The X.509 certificate used to sign the servers certificate - * @param url Connection target - */ - public static HttpsURLConnection openCAConnection(byte[] certificate, URL url) - throws TlsHelperException, IOException { - try { - // Load CA - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Certificate ca = cf.generateCertificate(new ByteArrayInputStream(certificate)); - - // Create a KeyStore containing our trusted CAs - String keyStoreType = KeyStore.getDefaultType(); - KeyStore keyStore = KeyStore.getInstance(keyStoreType); - keyStore.load(null, null); - keyStore.setCertificateEntry("ca", ca); - - // Create a TrustManager that trusts the CAs in our KeyStore - String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); - tmf.init(keyStore); - - // Create an SSLContext that uses our TrustManager - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, tmf.getTrustManagers(), null); - - // Tell the URLConnection to use a SocketFactory from our SSLContext - HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); - urlConnection.setSSLSocketFactory(context.getSocketFactory()); - - return urlConnection; - } catch (CertificateException | KeyManagementException | KeyStoreException | NoSuchAlgorithmException e) { - throw new TlsHelperException(e); - } - } } diff --git a/OpenKeychain/src/main/res/layout/add_keyserver_dialog.xml b/OpenKeychain/src/main/res/layout/add_keyserver_dialog.xml index 78e9247ea..b83681537 100644 --- a/OpenKeychain/src/main/res/layout/add_keyserver_dialog.xml +++ b/OpenKeychain/src/main/res/layout/add_keyserver_dialog.xml @@ -9,21 +9,37 @@ android:paddingRight="24dp" android:paddingTop="16dp"> - + android:layout_marginBottom="8dp"> + + + + + + + + android:checked="true" + android:text="@string/label_only_trusted_keyserver" /> \ No newline at end of file diff --git a/OpenKeychain/src/main/res/values-cs/strings.xml b/OpenKeychain/src/main/res/values-cs/strings.xml index 6b6bc956b..79a5a276c 100644 --- a/OpenKeychain/src/main/res/values-cs/strings.xml +++ b/OpenKeychain/src/main/res/values-cs/strings.xml @@ -135,7 +135,7 @@ Zapnout kompresi Zašifrovat jména souborů Skrýt příjemce - Ověřit keyserver + Ověřit keyserver Zadejte URL keyserveru OpenPGP keyserver Vyhledat klíče na vybraném OpenPGP keyserveru (protokol HKP) @@ -496,7 +496,7 @@ <žádný> Přidat keyserver - Keyserver ověřen! + Keyserver ověřen! Keyserver přidán bez verifikace. Neplatná URL! Nepodařilo se připojit ke key severu. Prosím ověřte URL a vaše připojení k internetu. diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml index 291ebf238..0e4a43c6f 100644 --- a/OpenKeychain/src/main/res/values-de/strings.xml +++ b/OpenKeychain/src/main/res/values-de/strings.xml @@ -155,7 +155,7 @@ Komprimierung aktivieren Dateinamen verschlüsseln Empfänger verbergen - Schlüsselserver verifizieren + Schlüsselserver verifizieren Schlüsselserver-URL eingeben Schlüsselserver löschen Design @@ -386,7 +386,7 @@ Lösche Schlüssel… Zusammenführung: Sichere in den Zwischenspeicher... Zusammenführung: Reimportiere... - Schlüsselserver wird verifiziert… + Schlüsselserver wird verifiziert… Orbot wird gestartet… Via Name, E-Mail suchen... @@ -691,7 +691,7 @@ Schlüsselserver hinzufügen Schlüsselserver bearbeiten - Schlüsselserver verifiziert! + Schlüsselserver verifiziert! Schlüsselserver ohne Verifikation hinzugefügt. Ungültige URL! Verbindung zum Schlüsselserver fehlgeschlagen. Bitte überprüfe die URL und deine Internetverbindung. diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml index 043918c64..a6849c542 100644 --- a/OpenKeychain/src/main/res/values-es/strings.xml +++ b/OpenKeychain/src/main/res/values-es/strings.xml @@ -155,7 +155,7 @@ Habilitar compresión Cifrar nombres de ficheros Ocultar receptores - Verificar servidor de claves + Verificar servidor de claves Introduzca URL de servidor de claves Borrar servidor de claves Tema decorativo @@ -386,7 +386,7 @@ borrando claves... consolidación: guardando en caché... consolidación: reimportando - verificando servidor de claves... + verificando servidor de claves... Iniciando Orbot... Buscar mediante Nombre, Correo electrónico... @@ -691,7 +691,7 @@ Añadir servidor de claves Editar servidor de claves - ¡Servidor de claves verificado! + ¡Servidor de claves verificado! Servidor de claves añadido sin verificación ¡URL no válida! Fallo al conectar al servidor de claves. Por favor, compuebe la URL y su conexión a Internet. diff --git a/OpenKeychain/src/main/res/values-eu/strings.xml b/OpenKeychain/src/main/res/values-eu/strings.xml index de4fb68d6..f57297498 100644 --- a/OpenKeychain/src/main/res/values-eu/strings.xml +++ b/OpenKeychain/src/main/res/values-eu/strings.xml @@ -154,7 +154,7 @@ Gaitu konpresioa Enkriptatu agirizenak Ezkutatu jasotzaileak - Egiaztatu giltza-zerbitzaria + Egiaztatu giltza-zerbitzaria Sartu giltza-zerbitzariaren URL-a Ezabatu giltza-zerbitzaria Azalgaia @@ -376,7 +376,7 @@ giltzak ezabatzen... sendotu: katxean gordetzen... sendotu: berrinportatzen... - giltza-zerbitzaria egiaztatzen... + giltza-zerbitzaria egiaztatzen... Orbot Abiarazten... Bilatu Izena, Post@... bidez @@ -675,7 +675,7 @@ Gehitu giltza-zerbitzaria Editatu giltza-zerbitzaria - Giltza-zerbitzaria egiaztatuta! + Giltza-zerbitzaria egiaztatuta! Giltza-zerbitzaria gehituta egiaztapen gabe. URL baliogabea! Hutsegitea giltza-zerbitzariarekin elkartzerakoan. Mesedez egiaztatu URL-a eta zure internet elkarketa. diff --git a/OpenKeychain/src/main/res/values-fa/strings.xml b/OpenKeychain/src/main/res/values-fa/strings.xml index 86d8ab5cd..790d5e90c 100644 --- a/OpenKeychain/src/main/res/values-fa/strings.xml +++ b/OpenKeychain/src/main/res/values-fa/strings.xml @@ -146,7 +146,7 @@ فشرده‌کردن رمزگذاری اسمِ فایل‌ها مخفی‌کردن گیرنده‌ها - بررسی سرورِ کلیدها + بررسی سرورِ کلیدها آدرس URL سرورِ کلید را وارد کنید حذف سرورهای کلید قالب diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml index 4a6c2bbfe..b5e5f3d53 100644 --- a/OpenKeychain/src/main/res/values-fr/strings.xml +++ b/OpenKeychain/src/main/res/values-fr/strings.xml @@ -155,7 +155,7 @@ Activer la compression Chiffrer les nom de fichier Cacher les destinataires - Vérifier le serveur de clefs + Vérifier le serveur de clefs Saisir l\'URL du serveur de clefs Supprimer le serveur de clefs Thème @@ -386,7 +386,7 @@ suppression des clefs... consolider : enregistrement dans le cache... consolider : réimportation... - vérification du serveur de clefs... + vérification du serveur de clefs... Démarrage d\'Orbot... Chercher par nom, adresse courriel... @@ -691,7 +691,7 @@ Ajouter un serveur de clefs Modifier le serveur de clefs - Le serveur de clefs a été vérifié ! + Le serveur de clefs a été vérifié ! Le serveur de clefs a été ajouté sans vérification. URL invalide ! Échec de connexion au serveur de clefs. Veuillez vérifier l\'URL et votre connexion Internet. diff --git a/OpenKeychain/src/main/res/values-it/strings.xml b/OpenKeychain/src/main/res/values-it/strings.xml index 9f58dc3ba..5b87c6ced 100644 --- a/OpenKeychain/src/main/res/values-it/strings.xml +++ b/OpenKeychain/src/main/res/values-it/strings.xml @@ -149,7 +149,7 @@ Abilitare compressione Codifica nome dei file Nascondi destinatari - Verificare server chiavi + Verificare server chiavi Inserisci URL server chiavi Cancella server chiavi Server chiavi OpenPGP diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml index 6f735b35b..789a35e75 100644 --- a/OpenKeychain/src/main/res/values-ja/strings.xml +++ b/OpenKeychain/src/main/res/values-ja/strings.xml @@ -155,7 +155,7 @@ 圧縮を有効 暗号化するファイル名 受信者を隠す - 鍵サーバを検証 + 鍵サーバを検証 鍵サーバのURLを入力 鍵サーバの削除 テーマ @@ -382,7 +382,7 @@ 鍵の削除中... 統合: キャッシュへ保存… 統合: 再インポート中… - 鍵サーバの検証... + 鍵サーバの検証... Orbotを始める... 名前、Email...で検索 @@ -674,7 +674,7 @@ 鍵サーバを追加 鍵サーバの編集 - 鍵サーバを検証しました! + 鍵サーバを検証しました! 鍵サーバを検証なしで追加した。 無効なURLです! 鍵サーバへの接続し失敗。URLとあなたのインターネット接続をチェックしてください。 diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml index 1a02fdc07..812376026 100644 --- a/OpenKeychain/src/main/res/values-nl/strings.xml +++ b/OpenKeychain/src/main/res/values-nl/strings.xml @@ -151,7 +151,7 @@ Compressie aanzetten Versleutel bestandsnamen Verberg ontvangers - Sleutelserver verifiëren + Sleutelserver verifiëren Voer sleutelserver-URL in Sleutelserver verwijderen Thema @@ -366,7 +366,7 @@ bezig met verwijderen van sleutels… consolidatie: bezig met opslaan naar cache… consolidatie: bezig met opnieuw importeren… - bezig met verifiëren van sleutelserver… + bezig met verifiëren van sleutelserver… Zoeken via naam, e-mail, ... @@ -648,7 +648,7 @@ Sleutelserver toevoegen Sleutelserver bewerken - Sleutelserver geverifieerd! + Sleutelserver geverifieerd! Sleutelserver toegevoegd zonder verificatie. Ongeldige URL! Kon niet verbinden met sleutelserver. Controleer de URL en je internetverbinding. diff --git a/OpenKeychain/src/main/res/values-ru/strings.xml b/OpenKeychain/src/main/res/values-ru/strings.xml index 55a5afa5e..6b73d367c 100644 --- a/OpenKeychain/src/main/res/values-ru/strings.xml +++ b/OpenKeychain/src/main/res/values-ru/strings.xml @@ -152,7 +152,7 @@ Использовать сжатие Шифровать имена файлов Скрыть получателей - Подтвердить сервер ключей + Подтвердить сервер ключей Введите адрес сервера ключей Удалить сервер ключей Тема @@ -364,7 +364,7 @@ удаление ключей... объединение: сохранение в кэш... объединение: реимпорт... - подтверждение сервера ключей... + подтверждение сервера ключей... Искать через Имя, Email... @@ -568,7 +568,7 @@ <нет> Добавить сервер ключей - Сервер ключей подтверждён! + Сервер ключей подтверждён! Сервер ключей добавлен без подтверждения. Неправильный адрес! diff --git a/OpenKeychain/src/main/res/values-sr/strings.xml b/OpenKeychain/src/main/res/values-sr/strings.xml index 5c6d03950..ed7bce5f7 100644 --- a/OpenKeychain/src/main/res/values-sr/strings.xml +++ b/OpenKeychain/src/main/res/values-sr/strings.xml @@ -155,7 +155,7 @@ Омогући компресију Шифруј имена фајлова Сакриј примаоце - Овери сервер кључева + Овери сервер кључева Унесите УРЛ сервера кључева Обриши сервер кључева Тема @@ -390,7 +390,7 @@ бришем кључеве… учвршћивање: уписујем у кеш… учвршћивање: поново увозим… - оверавам сервер кључева… + оверавам сервер кључева… Покрећем Орбот… Тражи преко имена, е-адресе… @@ -709,7 +709,7 @@ Додај сервер кључева Промени сервер кључева - Сервер кључева оверен! + Сервер кључева оверен! Сервер кључева додат без оверивања. Неисправан УРЛ! Неуспех повезивања са сервером кључева. Проверите УРЛ и вашу везу са интернетом. diff --git a/OpenKeychain/src/main/res/values-sv/strings.xml b/OpenKeychain/src/main/res/values-sv/strings.xml index 1ccac9199..4a0a9d083 100644 --- a/OpenKeychain/src/main/res/values-sv/strings.xml +++ b/OpenKeychain/src/main/res/values-sv/strings.xml @@ -135,7 +135,7 @@ Aktivera kompression Kryptera filnamn Dölj mottagare - Verifiera nyckelserver + Verifiera nyckelserver Ange nyckelserver-URL OpenPGP nyckelservrar Sök nycklar på valda OpenPGP nyckelservrar (HKP-protokollet) @@ -313,7 +313,7 @@ raderar nycklar… konsolidera: sparar till cache… konsolidera: återimporterar… - verifierar nyckelserver... + verifierar nyckelserver... Söker via Namn, E-post... @@ -565,7 +565,7 @@ <ingen> Lägg till nyckelserver - Nyckelserver verifierad! + Nyckelserver verifierad! Nyckelserver tillagd utan verifiering. Ogiltig URL! Misslyckades med att ansluta till nyckelserver. Kontrollera URL:en och din internetanslutning. diff --git a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml index 74d1cd781..87144422d 100644 --- a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml +++ b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml @@ -149,7 +149,7 @@ 啓用壓縮 加密檔名 隱藏收件人 - 驗證金鑰伺服器 + 驗證金鑰伺服器 輸入金鑰伺服器網址 刪除金鑰伺服器 主題 @@ -362,7 +362,7 @@ 正在驗證完整性… 正在安全地刪除 \'%s\'... 正在刪除金鑰… - 正在驗證金鑰伺服器... + 正在驗證金鑰伺服器... 正在啟動Orbot... 使用姓名,電子郵件尋找... @@ -625,7 +625,7 @@ 新增金鑰伺服器 編輯金鑰伺服器 - 已驗證金鑰伺服器! + 已驗證金鑰伺服器! 已新增金鑰伺服器但並未進行驗證。 URL無效! 連線到金鑰伺服器失敗。請確認金鑰伺服器網址及網路連線。 diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 62083cbb4..c83b598ed 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -172,8 +172,9 @@ "Encrypt filenames" "Hide recipients" - "Verify keyserver" - "Enter keyserver URL" + "Test connection" + "Only trusted keyserver" + "URL" "Delete keyserver" "Theme" @@ -445,7 +446,7 @@ "consolidate: saving to cache…" "consolidate: reimporting…" - "verifying keyserver…" + "verifying connection…" "Starting Orbot…" @@ -778,9 +779,10 @@ "Add keyserver" "Edit keyserver" - "Keyserver verified!" + "Connection verified!" "Keyserver added without verification." "Invalid URL!" + "Keyserver is not one of the trusted ones (no pinned certificate available)!" "Failed to connect to keyserver. Please check the URL and your Internet connection." "%s deleted" "Cannot delete last keyserver. At least one is required!" -- cgit v1.2.3