1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
/*
* Copyright (c) 2012-2019 Arne Schwabe
* Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
*/
package de.blinkt.openvpn.core
import android.app.AlertDialog
import android.app.Dialog
import android.content.ComponentName
import android.content.DialogInterface
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.text.InputType
import android.widget.EditText
import androidx.fragment.app.DialogFragment
import de.blinkt.openvpn.R
import de.blinkt.openvpn.core.OpenVPNService.EXTRA_CHALLENGE_TXT
class PasswordDialogFragment : DialogFragment() {
private var mService: IOpenVPNServiceInternal? = null
private val mConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName,
service: IBinder) {
mService = IOpenVPNServiceInternal.Stub.asInterface(service)
}
override fun onServiceDisconnected(arg0: ComponentName) {
mService = null
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val intent = Intent(activity, OpenVPNService::class.java)
intent.action = OpenVPNService.START_SERVICE
requireActivity().bindService(intent, mConnection, 0)
}
override fun onDestroy() {
super.onDestroy()
requireActivity().unbindService(mConnection)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val title = requireArguments().getString("title")
val echo = requireArguments().getBoolean("echo")
val finish = requireArguments().getBoolean("finish")
val input = EditText(activity)
if (!echo)
input.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
return AlertDialog.Builder(activity)
.setTitle("Challenge/Response Authentification")
.setMessage(title)
.setView(input)
.setPositiveButton(android.R.string.ok) { _, _ ->
try {
mService?.challengeResponse(input.text.toString())
if (finish) requireActivity().finish()
} catch (e: RemoteException) {
VpnStatus.logException(e)
e.printStackTrace()
}
}
.setNegativeButton(R.string.cancel
) { _, _ -> if (finish) requireActivity().finish() }
.create()
}
companion object {
fun newInstance(intent: Intent, finish: Boolean): PasswordDialogFragment? {
val extras = intent.extras ?: return null
val challenge = extras.getString(EXTRA_CHALLENGE_TXT, "R,E:(empty challenge text)")
val message = challenge.split(":", limit = 2)[1]
val flagsStr = challenge.split(":", limit = 2)[0]
val flags = flagsStr.split(",")
var echo = false
var response = false
for (flag in flags) {
if (flag == "R") response = true
else if (flag == "E") echo = true
}
if (!response) {
VpnStatus.logError("Error unrecognised challenge from Server: $challenge")
return null
}
val frag = PasswordDialogFragment()
val args = Bundle()
args.putString("title", message)
args.putBoolean("echo", echo)
args.putBoolean("finish", finish)
frag.arguments = args
return frag
}
}
}
|