Added a quick fix for accepting self signed certificates.

This commit is contained in:
Amine 2017-08-04 21:39:45 +02:00 committed by Amine Bou
parent d768d2232b
commit 0ef59c9b91
9 changed files with 85 additions and 7 deletions

View File

@ -2,6 +2,7 @@ package apps.amine.bou.readerforselfoss
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.support.constraint.ConstraintLayout import android.support.constraint.ConstraintLayout
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar import android.support.v7.widget.Toolbar
@ -43,7 +44,8 @@ class AddSourceActivity : AppCompatActivity() {
var api: SelfossApi? = null var api: SelfossApi? = null
try { try {
api = SelfossApi(this, this@AddSourceActivity) val prefs = PreferenceManager.getDefaultSharedPreferences(this)
api = SelfossApi(this, this@AddSourceActivity, prefs.getBoolean("isSelfSignedCert", false))
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
mustLoginToAddSource() mustLoginToAddSource()
} }

View File

@ -139,7 +139,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
customTabActivityHelper = CustomTabActivityHelper() customTabActivityHelper = CustomTabActivityHelper()
api = SelfossApi(this, this@HomeActivity) val dirtyPref = PreferenceManager.getDefaultSharedPreferences(this)
api = SelfossApi(this, this@HomeActivity, dirtyPref.getBoolean("isSelfSignedCert", false))
items = ArrayList() items = ArrayList()
appColors = AppColors(this@HomeActivity) appColors = AppColors(this@HomeActivity)

View File

@ -37,6 +37,7 @@ import io.fabric.sdk.android.Fabric
class LoginActivity : AppCompatActivity() { class LoginActivity : AppCompatActivity() {
private var inValidCount: Int = 0 private var inValidCount: Int = 0
private var isWithSelfSignedCert = false
private var isWithLogin = false private var isWithLogin = false
private var isWithHTTPLogin = false private var isWithHTTPLogin = false
@ -101,6 +102,15 @@ class LoginActivity : AppCompatActivity() {
val mPasswordLayout: TextInputLayout = findViewById(R.id.passwordLayout) val mPasswordLayout: TextInputLayout = findViewById(R.id.passwordLayout)
val mHTTPPasswordLayout: TextInputLayout = findViewById(R.id.httpPasswordInput) val mHTTPPasswordLayout: TextInputLayout = findViewById(R.id.httpPasswordInput)
val mEmailSignInButton: Button = findViewById(R.id.email_sign_in_button) val mEmailSignInButton: Button = findViewById(R.id.email_sign_in_button)
val selfHostedSwitch: Switch = findViewById(R.id.withSelfhostedCert)
val warningTextview: TextView = findViewById(R.id.warningText)
selfHostedSwitch.setOnCheckedChangeListener {_, b ->
isWithSelfSignedCert = !isWithSelfSignedCert
val visi: Int = if (b) View.VISIBLE else View.GONE
warningTextview.visibility = visi
}
mPasswordView.setOnEditorActionListener(TextView.OnEditorActionListener { _, id, _ -> mPasswordView.setOnEditorActionListener(TextView.OnEditorActionListener { _, id, _ ->
if (id == R.id.login || id == EditorInfo.IME_NULL) { if (id == R.id.login || id == EditorInfo.IME_NULL) {
@ -196,9 +206,10 @@ class LoginActivity : AppCompatActivity() {
editor.putString("httpUserName", httpLogin) editor.putString("httpUserName", httpLogin)
editor.putString("password", password) editor.putString("password", password)
editor.putString("httpPassword", httpPassword) editor.putString("httpPassword", httpPassword)
editor.putBoolean("isSelfSignedCert", isWithSelfSignedCert)
editor.apply() editor.apply()
val api = SelfossApi(this, this@LoginActivity) val api = SelfossApi(this, this@LoginActivity, isWithSelfSignedCert)
api.login().enqueue(object : Callback<SuccessResponse> { api.login().enqueue(object : Callback<SuccessResponse> {
private fun preferenceError(t: Throwable) { private fun preferenceError(t: Throwable) {
editor.remove("url") editor.remove("url")

View File

@ -2,6 +2,7 @@ package apps.amine.bou.readerforselfoss
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
@ -36,7 +37,10 @@ class SourcesActivity : AppCompatActivity() {
val mFab: FloatingActionButton = findViewById(R.id.fab) val mFab: FloatingActionButton = findViewById(R.id.fab)
val mRecyclerView: RecyclerView = findViewById(R.id.activity_sources) val mRecyclerView: RecyclerView = findViewById(R.id.activity_sources)
val mLayoutManager = LinearLayoutManager(this) val mLayoutManager = LinearLayoutManager(this)
val api = SelfossApi(this, this@SourcesActivity)
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
val api = SelfossApi(this, this@SourcesActivity, prefs.getBoolean("isSelfSignedCert", false))
var items: ArrayList<Sources> = ArrayList() var items: ArrayList<Sources> = ArrayList()
mFab.attachToRecyclerView(mRecyclerView) mFab.attachToRecyclerView(mRecyclerView)

View File

@ -23,26 +23,66 @@ import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import javax.net.ssl.*
// codebeat:disable[ARITY,TOO_MANY_FUNCTIONS] // codebeat:disable[ARITY,TOO_MANY_FUNCTIONS]
class SelfossApi(c: Context, callingActivity: Activity) { class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Boolean) {
private lateinit var service: SelfossService private lateinit var service: SelfossService
private val config: Config = Config(c) private val config: Config = Config(c)
private val userName: String private val userName: String
private val password: String private val password: String
fun OkHttpClient.Builder.maybeWithSelfSigned(isWithSelfSignedCert: Boolean): OkHttpClient.Builder =
if (isWithSelfSignedCert) {
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate> =
arrayOf()
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
}
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
}
})
// Install the all-trusting trust manager
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
val sslSocketFactory = sslContext.socketFactory
OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
.hostnameVerifier { _, _ -> true }
} catch (e: Exception) {
throw RuntimeException(e)
}
} else {
this
}
fun Credentials.createAuthenticator(): DispatchingAuthenticator = fun Credentials.createAuthenticator(): DispatchingAuthenticator =
DispatchingAuthenticator.Builder() DispatchingAuthenticator.Builder()
.with("digest", DigestAuthenticator(this)) .with("digest", DigestAuthenticator(this))
.with("basic", BasicAuthenticator(this)) .with("basic", BasicAuthenticator(this))
.build() .build()
fun DispatchingAuthenticator.getHttpClien(): OkHttpClient { fun DispatchingAuthenticator.getHttpClien(isWithSelfSignedCert: Boolean): OkHttpClient {
val authCache = ConcurrentHashMap<String, CachingAuthenticator>() val authCache = ConcurrentHashMap<String, CachingAuthenticator>()
return OkHttpClient return OkHttpClient
.Builder() .Builder()
.maybeWithSelfSigned(isWithSelfSignedCert)
.authenticator(CachingAuthenticatorDecorator(this, authCache)) .authenticator(CachingAuthenticatorDecorator(this, authCache))
.addInterceptor(AuthenticationCacheInterceptor(authCache)) .addInterceptor(AuthenticationCacheInterceptor(authCache))
.build() .build()
@ -71,7 +111,7 @@ class SelfossApi(c: Context, callingActivity: Activity) {
Retrofit Retrofit
.Builder() .Builder()
.baseUrl(config.baseUrl) .baseUrl(config.baseUrl)
.client(authenticator.getHttpClien()) .client(authenticator.getHttpClien(isWithSelfSignedCert))
.addConverterFactory(GsonConverterFactory.create(gson)) .addConverterFactory(GsonConverterFactory.create(gson))
.build() .build()
service = retrofit.create(SelfossService::class.java) service = retrofit.create(SelfossService::class.java)

View File

@ -138,6 +138,20 @@
android:hint="@string/prompt_http_password" /> android:hint="@string/prompt_http_password" />
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<Switch
android:id="@+id/withSelfhostedCert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/self_hosted_cert_switch" />
<TextView
android:id="@+id/warningText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/self_signed_cert_warning"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:visibility="gone" />
<Button <Button
android:id="@+id/email_sign_in_button" android:id="@+id/email_sign_in_button"
style="?android:textAppearanceSmall" style="?android:textAppearanceSmall"

View File

@ -136,4 +136,6 @@
<string name="login_debug_on">Toutes les erreurs de connexion vont être loguées</string> <string name="login_debug_on">Toutes les erreurs de connexion vont être loguées</string>
<string name="login_debug_off">Aucune erreur de connexion ne sera loguée</string> <string name="login_debug_off">Aucune erreur de connexion ne sera loguée</string>
<string name="login_menu_debug">Debug</string> <string name="login_menu_debug">Debug</string>
<string name="self_hosted_cert_switch">Certificat auto-signé ?</string>
<string name="self_signed_cert_warning">Pour des raisons de sécurités, les certificats auto-signés sont désactivés par défaut. En les activant, je ne serais pas responsable de quelconques problèmes de sécurité rencontrés.</string>
</resources> </resources>

View File

@ -136,4 +136,6 @@
<string name="login_debug_on">Any error on the login page will be logged</string> <string name="login_debug_on">Any error on the login page will be logged</string>
<string name="login_debug_off">No log on the login page</string> <string name="login_debug_off">No log on the login page</string>
<string name="login_menu_debug">Debug</string> <string name="login_menu_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
</resources> </resources>

View File

@ -138,4 +138,6 @@
<string name="login_debug_on">Any error on the login page will be logged</string> <string name="login_debug_on">Any error on the login page will be logged</string>
<string name="login_debug_off">No log on the login page</string> <string name="login_debug_off">No log on the login page</string>
<string name="login_menu_debug">Debug</string> <string name="login_menu_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
</resources> </resources>