Added signature system for sites which do not require certs

Also broke a bunch of things, but we'll get there I swear.
This commit is contained in:
Corewala 2022-05-18 12:18:59 -04:00
parent 29fe06ba54
commit da4702b1a0
9 changed files with 53 additions and 20 deletions

View File

@ -10,6 +10,7 @@ sealed class GemState {
data class NotGeminiRequest(val uri: URI) : GemState()
data class ResponseGemtext(val uri: URI, val header: GeminiResponse.Header, val lines: List<String>) : GemState()
data class ResponseInput(val uri: URI, val header: GeminiResponse.Header) : GemState()
class Redirect(val uri: String) : GemState()
data class ResponseText(val uri: URI, val header: GeminiResponse.Header, val content: String) : GemState()
data class ResponseImage(val uri: URI, val header: GeminiResponse.Header, val cacheUri: Uri) : GemState()
data class ResponseBinary(val uri: URI, val header: GeminiResponse.Header, val cacheUri: Uri) : GemState()

View File

@ -8,7 +8,6 @@ import java.net.URI
interface Datasource {
fun request(address: String, forceDownload: Boolean, clientCertPassword: String?, onUpdate: (state: GemState) -> Unit)
fun canGoBack(): Boolean
fun goBack(onUpdate: (state: GemState) -> Unit)
companion object{
fun factory(context: Context, history: BuranHistory): Datasource {

View File

@ -8,6 +8,7 @@ import corewala.buran.OppenURI
import corewala.buran.io.GemState
import corewala.buran.io.database.history.BuranHistory
import corewala.buran.io.keymanager.BuranKeyManager
import corewala.toURI
import corewala.toUri
import java.io.*
import java.lang.IllegalStateException
@ -30,7 +31,7 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
private var socketFactory: SSLSocketFactory? = null
override fun request(address: String, forceDownload: Boolean, clientCertPassword: String?, onUpdate: (state: GemState) -> Unit) {
override fun request(address: String, forceDownload: Boolean, clientCertPassword: String?, onUpdate: (state: GemState) -> Unit) {
this.forceDownload = forceDownload
this.onUpdate = onUpdate
@ -113,7 +114,7 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
when {
header.code == GeminiResponse.INPUT -> onUpdate(GemState.ResponseInput(uri, header))
header.code == GeminiResponse.REDIRECT -> request(resolve(uri.host, header.meta), false, null, onUpdate)
header.code == GeminiResponse.REDIRECT -> onUpdate(GemState.Redirect(resolve(uri.host, header.meta)))
header.code == GeminiResponse.CLIENT_CERTIFICATE_REQUIRED -> onUpdate(GemState.ClientCertRequired(uri, header))
header.code != GeminiResponse.SUCCESS -> onUpdate(GemState.ResponseError(header))
header.meta.startsWith("text/gemini") -> getGemtext(bufferedReader, uri, header, onUpdate)
@ -217,11 +218,6 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
override fun canGoBack(): Boolean = runtimeHistory.isEmpty() || runtimeHistory.size > 1
override fun goBack(onUpdate: (state: GemState) -> Unit) {
runtimeHistory.removeLast()
request(runtimeHistory.last().toString(), false, null, onUpdate)
}
//This just forces the factory to rebuild before the next request
fun invalidate() {
socketFactory = null

View File

@ -20,8 +20,7 @@ class BuranKeyManager(val context: Context, val onKeyError: (error: String) -> U
//If the user has a key loaded load it here - or else return null
fun getFactory(clientCertPassword: String?): KeyManagerFactory? {
return when {
clientCertPassword != null -> {
return when { !clientCertPassword.isNullOrEmpty() -> {
lastCallUsedKey = true
val keyStore: KeyStore = KeyStore.getInstance("pkcs12")

View File

@ -17,6 +17,7 @@ import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import androidx.activity.viewModels
import androidx.annotation.Nullable
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
@ -48,6 +49,7 @@ import corewala.buran.ui.modals_menus.about.AboutDialog
import corewala.buran.ui.modals_menus.history.HistoryDialog
import corewala.buran.ui.modals_menus.overflow.OverflowPopup
import corewala.buran.ui.settings.SettingsActivity
import kotlinx.android.synthetic.main.bookmark.*
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
@ -115,8 +117,13 @@ class GemActivity : AppCompatActivity() {
private val inlineImage: (link: URI, adapterPosition: Int) -> Unit = { uri, position: Int ->
if(getInternetStatus()){
omniTerm.imageAddress(uri.toString())
val clientCertPassword = if(isHostSigned(uri)){
certPassword
}else{
null
}
omniTerm.uri.let{
model.requestInlineImage(URI.create(it.toString())){ imageUri ->
model.requestInlineImage(URI.create(it.toString()), clientCertPassword){ imageUri ->
imageUri?.let{
runOnUiThread {
loadImage(position, imageUri)
@ -249,6 +256,20 @@ class GemActivity : AppCompatActivity() {
binding.addressEdit.requestFocus()
inSearch = true
}
R.id.overflow_menu_sign -> {
if(prefs.getBoolean("use_biometrics", false) and certPassword.isNullOrEmpty()){
biometricSecureRequest(binding.addressEdit.text.toString())
}else{
if(certPassword.isNullOrEmpty()){
certPassword = prefs.getString(
Buran.PREF_KEY_CLIENT_CERT_PASSWORD,
null
)
}
gemRequest(binding.addressEdit.text.toString())
}
}
R.id.overflow_menu_bookmark -> {
val name = adapter.inferTitle()
BookmarkDialog(
@ -407,6 +428,8 @@ class GemActivity : AppCompatActivity() {
.show()
}
is GemState.Redirect -> gemRequest(state.uri)
is GemState.ClientCertRequired -> runOnUiThread {
loadingView(false)
val builder = AlertDialog.Builder(this, R.style.AppDialogTheme)
@ -463,12 +486,17 @@ class GemActivity : AppCompatActivity() {
val download = getString(R.string.download)
if(getInternetStatus()) {
val clientCertPassword = if(isHostSigned(state.uri)){
certPassword
}else{
null
}
AlertDialog.Builder(this, R.style.AppDialogTheme)
.setTitle("$download: ${state.header.meta}")
.setMessage("${state.uri}")
.setPositiveButton(getString(R.string.download).toUpperCase()) { _, _ ->
loadingView(true)
model.requestBinaryDownload(state.uri)
model.requestBinaryDownload(state.uri, clientCertPassword)
}
.setNegativeButton(getString(R.string.cancel).toUpperCase()) { _, _ -> }
.show()
@ -755,11 +783,16 @@ class GemActivity : AppCompatActivity() {
return false
}
private fun gemRequest(address: String){
if(address.toURI().host != omniTerm.getCurrent().toURI().host) {
certPassword = null
private fun isHostSigned(uri: URI): Boolean{
if((uri.host != omniTerm.getCurrent().toURI().host) && !certPassword.isNullOrEmpty()) {
return false
}
println(certPassword)
return true
}
private fun gemRequest(address: String){
val clientCertAllowed = isHostSigned(address.toURI())
if(!clientCertAllowed) certPassword = null
if(getInternetStatus()){
if(initialised){

View File

@ -28,15 +28,15 @@ class GemViewModel: ViewModel() {
}
}
fun requestBinaryDownload(uri: URI) {
gemini.request(uri.toString(), true, null){ state ->
fun requestBinaryDownload(uri: URI, clientCertPassword: String?) {
gemini.request(uri.toString(), true, clientCertPassword){ state ->
onState(state)
}
}
//todo - same action as above... refactor
fun requestInlineImage(uri: URI, onImageReady: (cacheUri: Uri?) -> Unit){
gemini.request(uri.toString(), false, null){ state ->
fun requestInlineImage(uri: URI, clientCertPassword: String?, onImageReady: (cacheUri: Uri?) -> Unit){
gemini.request(uri.toString(), false, clientCertPassword){ state ->
when (state) {
is GemState.ResponseImage -> onImageReady(state.cacheUri)
else -> onState(state)

View File

@ -4,6 +4,9 @@
<item
android:id="@+id/overflow_menu_search"
android:title="@string/search"/>
<item
android:id="@+id/overflow_menu_sign"
android:title="@string/sign"/>
<item
android:id="@+id/overflow_menu_bookmark"
android:title="@string/add_bookmark"/>

View File

@ -73,6 +73,7 @@
<string name="confirm_your_identity">Confirmez votre identité</string>
<string name="use_biometric_unlock">Utilisez vos informations biométriques pour continuer</string>
<string name="biometric_cert_verification">Certificat Client biométrique</string>
<string name="sign">Certifier</string>
<string name="set_home_capsule">Choisir comme capsule d\'accueil</string>
<string name="check_for_updates">Rechercher des nouvelles versions</string>
<string name="new_version_available">Nouvelle version disponible</string>

View File

@ -73,6 +73,7 @@
<string name="confirm_your_identity">Confirm your identity</string>
<string name="use_biometric_unlock">Verify your biometric credentials to continue</string>
<string name="biometric_cert_verification">Client Certificate biometrics</string>
<string name="sign">Sign</string>
<string name="set_home_capsule">Set home capsule</string>
<string name="check_for_updates">Check for updates</string>
<string name="new_version_available">New version available</string>