diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index a5e16a10..84d8cd6c 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -122,9 +122,34 @@ static const char *translate_errorcode(uint16_t scode) } } +static void get_password(char *aor, char *password) +{ + LOGD("getting password of AoR %s\n", aor); + + JavaVM *javaVM = g_ctx.javaVM; + JNIEnv *env; + jint res = (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_6); + if (res != JNI_OK) { + res = (*javaVM)->AttachCurrentThread(javaVM, &env, NULL); + if (JNI_OK != res) { + LOGE("failed to AttachCurrentThread, ErrorCode = %d\n", res); + return; + } + } + + jmethodID methodId = (*env)->GetMethodID(env, g_ctx.mainActivityClz, "getPassword", + "(Ljava/lang/String;)Ljava/lang/String;"); + jstring javaAoR = (*env)->NewStringUTF(env, aor); + jstring javaPassword = (*env)->CallObjectMethod(env, g_ctx.mainActivityObj, methodId, javaAoR); + const char *pwd = (*env)->GetStringUTFChars(env, javaPassword, 0); + strcpy(password, pwd); + (*env)->ReleaseStringUTFChars(env, javaPassword, pwd); +} + static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { + (void)arg; const char *event; char event_buf[256]; char ua_buf[32]; @@ -196,6 +221,9 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev, case UA_EVENT_AUDIO_ERROR: mem_deref(call); return; + case UA_EVENT_GET_PASSWORD: + get_password((char *)ua, (char *)call); + return; default: return; } @@ -218,6 +246,18 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev, } } + if (ev == UA_EVENT_GET_PASSWORD) { + jmethodID methodId = (*env)->GetMethodID(env, g_ctx.mainActivityClz, "getPassword", + "(Ljava/lang/String;)Ljava/lang/String;"); + sprintf(ua_buf, "%lu", (unsigned long)ua); + jstring javaUA = (*env)->NewStringUTF(env, ua_buf); + jstring javaPassword = (*env)->CallObjectMethod(env, g_ctx.mainActivityObj, methodId, javaUA); + const char *password = (*env)->GetStringUTFChars(env, javaPassword, 0); + strcpy((char *)call, password); + (*env)->ReleaseStringUTFChars(env, javaPassword, password); + return; + } + jmethodID methodId = (*env)->GetMethodID(env, g_ctx.mainActivityClz, "uaEvent", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); diff --git a/app/src/main/kotlin/com/tutpro/baresip/Account.kt b/app/src/main/kotlin/com/tutpro/baresip/Account.kt index 05394dd1..aa0da994 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Account.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Account.kt @@ -80,7 +80,8 @@ class Account(val accp: String) { if (authUser != "") res = res + ";auth_user=\"${authUser}\"" - if (authPass != "") res = res + ";auth_pass=\"${authPass}\"" + if ((authPass != "") && !MainActivity.aorPasswords.containsKey(aor)) + res = res + ";auth_pass=\"${authPass}\"" if (outbound.size > 0) { res = res + ";outbound=\"${outbound[0]}\"" diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt index 0521692c..1e1fa97d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt @@ -61,7 +61,10 @@ class AccountActivity : AppCompatActivity() { authUser.setText(acc.authUser) authPass = findViewById(R.id.AuthPass) as EditText - authPass.setText(acc.authPass) + if (MainActivity.aorPasswords.containsKey(aor)) + authPass.setText("") + else + authPass.setText(acc.authPass) outbound1 = findViewById(R.id.Outbound1) as EditText outbound2 = findViewById(R.id.Outbound2) as EditText @@ -223,7 +226,8 @@ class AccountActivity : AppCompatActivity() { val au = authUser.text.toString().trim() val ap = authPass.text.toString().trim() - if (((au != "") && (ap == "")) || ((au == "") && (ap != ""))) { + + if ((au == "") && (ap != "")) { Utils.alertView(this, getString(R.string.notice), getString(R.string.authentication_username_password_mismatch)) return false @@ -245,10 +249,11 @@ class AccountActivity : AppCompatActivity() { } } - if (ap != acc.authPass) { - if (Utils.checkPrintAscii(ap)) { + if ((ap != acc.authPass) && (ap != "")) { + if (Utils.checkPrintAscii(ap) && (ap.length <= 64)) { if (account_set_auth_pass(acc.accp, ap) == 0) { acc.authPass = account_auth_pass(acc.accp) + MainActivity.aorPasswords.remove(aor) // Log.d("Baresip", "New auth password is ${acc.authPass}") save = true } else { @@ -259,6 +264,11 @@ class AccountActivity : AppCompatActivity() { String.format(getString(R.string.invalid_authentication_password), ap)) return false } + } else { + if ((ap == "") && !MainActivity.aorPasswords.containsKey(aor)) { + MainActivity.aorPasswords.put(aor, acc.authPass) + save = true + } } val ob = ArrayList() diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 0b6e2816..52fc0124 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -843,6 +843,16 @@ class BaresipService: Service() { LocalBroadcastManager.getInstance(this).sendBroadcast(intent) } + @Keep + fun getPassword(aor: String): String { + if (!isServiceRunning) return "" + Log.d(LOG_TAG, "getPassword of $aor") + if (MainActivity.aorPasswords[aor] != null) + return MainActivity.aorPasswords[aor]!! + else + return "" + } + @Keep fun stopped(error: String) { Log.d(LOG_TAG, "Received 'stopped' from baresip with param '$error'") diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index 0e0275f9..7529818f 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -424,11 +424,13 @@ class MainActivity : AppCompatActivity() { } baresipService = Intent(this@MainActivity, BaresipService::class.java) + if (!BaresipService.isServiceRunning) { - baresipService.setAction("Start") - startService(baresipService) - Utils.requestPermission(this, Manifest.permission.RECORD_AUDIO, - RECORD_PERMISSION_REQUEST_CODE) + if (File(filesDir.absolutePath + "/accounts").exists()) { + var accounts = String(Utils.getFileContents(filesDir.absolutePath + "/accounts")!!, + Charsets.UTF_8).lines().toMutableList() + askAorPasswords(accounts) + } } if (intent.hasExtra("onStartup")) @@ -966,6 +968,53 @@ class MainActivity : AppCompatActivity() { builder.show() } + private fun askAorPasswords(accounts: MutableList) { + if (accounts.isNotEmpty()) { + val account = accounts.removeAt(0) + val params = account.substringAfter(">") + if ((Utils.paramValue(params, "auth_user") != "") && + (Utils.paramValue(params, "auth_pass") == "")) { + val aor = account.substringAfter("<").substringBefore(">") + val builder = AlertDialog.Builder(this) + builder.setTitle(String.format(getString(R.string.account_password), Utils.plainAor(aor))) + val viewInflated = LayoutInflater.from(this) + .inflate(R.layout.password_dialog, findViewById(android.R.id.content) as ViewGroup, + false) + val input = viewInflated.findViewById(R.id.password) as EditText + builder.setView(viewInflated) + builder.setPositiveButton(android.R.string.ok) { dialog, _ -> + dialog.dismiss() + val password = input.text.toString() + if ((password.length < 1) || (password.length > 64) || !Utils.checkPrintAscii(password)) { + Utils.alertView(this, getString(R.string.notice), + String.format(getString(R.string.invalid_authentication_password), password)) + accounts.add(0, account) + } else { + aorPasswords.put(aor, password) + } + askAorPasswords(accounts) + } + builder.setNegativeButton(android.R.string.cancel) { dialog, _ -> + dialog.cancel() + aorPasswords.put(aor, "") + askAorPasswords(accounts) + } + builder.show() + } else { + askAorPasswords(accounts) + } + } else { + startBaresip() + } + } + + private fun startBaresip() { + baresipService.setAction("Start") + startService(baresipService) + Utils.requestPermission(this, Manifest.permission.RECORD_AUDIO, + RECORD_PERMISSION_REQUEST_CODE) + } + private fun backup(password: String) { val files = arrayListOf("accounts", "calls", "config", "contacts", "messages", "uuid", "zrtp_cache.dat", "zrtp_zid", "cert.pem", "ca_cert", "ca_certs.crt") @@ -1365,6 +1414,7 @@ class MainActivity : AppCompatActivity() { var resumeUap = "" var resumeCall: Call? = null var resumeUri = "" + val aorPasswords = mutableMapOf() const val ACCOUNTS_CODE = 1 const val CONTACTS_CODE = 2 diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index 5fd188d6..5c89b63c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -97,6 +97,12 @@ object Utils { return if (domain == aor) "" else domain } + fun plainAor(aor: String): String { + return aor.substringAfter(":").substringBefore("@") + "@" + + aor.substringAfter("@").substringBefore(";") + .substringBefore(":") + } + fun checkAor(aor: String): Boolean { val p = aor.split(":") if (p.size == 2) diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 62cc32d2..d532100b 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -38,16 +38,19 @@ Tilin käyttäjän nimi, joka esiintyy SIP-sanomien From URI:ssa (vapaaehtoinen). Virheellinen tilin käyttäjän nimi \'%1$s\' - Käyttäjätunnus ja salasana ovat molemmat - annettava ellei kumpikin ole tyhjä. + Salasanaa ei + voi antaa ilman käyttäjätunnusta. Käyttäjätunnus Todentamiseen käytettävä - käyttäjätunnus, jos välityspalvelin vaatii sellaisen. + käyttäjätunnus, jos välityspalvelin vaatii sellaisen. Virheellinen käyttäjätunnus \'%1$s\' Salasana Todentamiseen käytettävä - salasana, jos välityspalvelin vaatii sellaisen. + salasana, jonka pituus on enintään 64 ASCII merkkiä. Jos + käyttäjätunnus on annettu, mutta salasanaa ei ole annettu, se + kysytään, kun baresip käynnistetään. + Virheellinen salasana \'%1$s\' Välityspalvelimet Yhden tai kahden @@ -356,4 +359,5 @@ Et voi soittaa puheluita tai vastata niihin ilman Mikrofoni-käyttöoikeutta. + Tilin %1$s salasana diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7b4e8060..1206d59f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -41,8 +41,7 @@ Your Name Name (if any) used in From URI of outbound requests. Invalid Display Name \'%1$s\' - Autentication Username and Authentication - Password must both be given or both must be empty. + Authentication Password cannot be given without Authentication Username. Authentication Username Authentication username if authentication of SIP @@ -50,8 +49,9 @@ Invalid Authentication Username \'%1$s\' Authentication Password - Authentication password if authentication of SIP - requests is required. + Authentication + Password up to 64 characters. If Authentication Username is given, but Password is not + given, it will be asked when baresip is started. Invalid Authentication Password \'%1$s\' Outbound Proxies @@ -318,4 +318,5 @@ and, if so, you gave correct Decrypt Password. You are not able to place or answer calls without Microphone permission. - \ No newline at end of file + Account %1$s Authentication Password +