From 2950bd9bea914571e83b72a8815797203d0c53f0 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 27 Mar 2020 10:56:44 +0100 Subject: [PATCH] android: Support requesting PINs instead of passwords --- .../android/logic/CharonVpnService.java | 17 +++++---- .../android/ui/LoginDialogFragment.java | 14 +++++-- .../libandroidbridge/backend/android_creds.c | 2 +- .../main/jni/libandroidbridge/charonservice.c | 7 ++-- .../main/jni/libandroidbridge/charonservice.h | 3 +- .../src/main/res/layout/login_dialog_pin.xml | 38 +++++++++++++++++++ .../app/src/main/res/values-de/strings.xml | 5 ++- .../app/src/main/res/values-pl/strings.xml | 3 ++ .../app/src/main/res/values-ru/strings.xml | 3 ++ .../app/src/main/res/values-ua/strings.xml | 3 ++ .../src/main/res/values-zh-rCN/strings.xml | 3 ++ .../src/main/res/values-zh-rTW/strings.xml | 3 ++ .../app/src/main/res/values/strings.xml | 3 ++ 13 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 src/frontends/android/app/src/main/res/layout/login_dialog_pin.xml diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java index 7163512345..dfe548f606 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java @@ -51,6 +51,7 @@ import org.strongswan.android.logic.VpnStateService.ErrorState; import org.strongswan.android.logic.VpnStateService.State; import org.strongswan.android.logic.imc.ImcState; import org.strongswan.android.logic.imc.RemediationInstruction; +import org.strongswan.android.ui.LoginDialogFragment; import org.strongswan.android.ui.MainActivity; import org.strongswan.android.ui.VpnLoginActivity; import org.strongswan.android.ui.VpnProfileControlActivity; @@ -798,13 +799,14 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe * * Note that this method is called from a thread of charon's thread pool. * + * @param pin whether a PIN or a password is requested * @return the password */ - private String getPassword() + private String getPassword(boolean pin) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - return mPasswordPrompt.getPassword(); + return mPasswordPrompt.getPassword(pin); } return null; } @@ -1460,12 +1462,13 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe } @RequiresApi(api = Build.VERSION_CODES.KITKAT) - private Notification buildNotification(boolean publicVersion) + private Notification buildNotification(boolean pin, boolean publicVersion) { CharonVpnService service = CharonVpnService.this; Intent intent = new Intent(service, VpnLoginActivity.class); intent.putExtra(VpnProfileDataSource.KEY_USERNAME, mCurrentProfile.getUsername()); + intent.putExtra(LoginDialogFragment.REQUEST_PIN, pin); PendingIntent pending = PendingIntent.getActivity(service, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); @@ -1473,7 +1476,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe new NotificationCompat.Builder(service, PASSWORD_CHANNEL) .setSmallIcon(R.drawable.ic_notification_warning) .setColor(ContextCompat.getColor(service, R.color.warning_text)) - .setContentTitle(getString(R.string.password_notification_prompt)) + .setContentTitle(getString(pin ? R.string.password_notification_prompt_pin : R.string.password_notification_prompt)) .setTimeoutAfter(PASSWORD_TIMEOUT * 1000) .setWhen(System.currentTimeMillis() + PASSWORD_TIMEOUT * 1000) .setUsesChronometer(true) @@ -1484,7 +1487,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe if (!publicVersion) { builder.setContentText(mCurrentProfile.getName()); - builder.setPublicVersion(buildNotification(true)); + builder.setPublicVersion(buildNotification(pin, true)); } Notification notification = builder.build(); @@ -1495,7 +1498,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe } @RequiresApi(api = Build.VERSION_CODES.N) - public String getPassword() + public String getPassword(boolean pin) { synchronized (mLock) { @@ -1507,7 +1510,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe } NotificationManagerCompat manager = NotificationManagerCompat.from(CharonVpnService.this); - manager.notify(PASSWORD_NOTIFICATION_ID, buildNotification(false)); + manager.notify(PASSWORD_NOTIFICATION_ID, buildNotification(pin, false)); try { return mPassword.get(PASSWORD_TIMEOUT, TimeUnit.SECONDS); diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LoginDialogFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LoginDialogFragment.java index 2efcc9fc4b..159497a4b5 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LoginDialogFragment.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LoginDialogFragment.java @@ -33,6 +33,8 @@ import androidx.appcompat.app.AppCompatDialogFragment; */ public class LoginDialogFragment extends AppCompatDialogFragment { + public static final String REQUEST_PIN = "REQUEST_PIN"; + private OnLoginDialogFragmentListener mListener; /** @@ -55,15 +57,19 @@ public class LoginDialogFragment extends AppCompatDialogFragment public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle profileInfo = getArguments(); + final boolean pin = profileInfo.getBoolean(REQUEST_PIN); LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.login_dialog, null); - EditText username = view.findViewById(R.id.username); - username.setText(profileInfo.getString(VpnProfileDataSource.KEY_USERNAME)); + View view = inflater.inflate(pin ? R.layout.login_dialog_pin : R.layout.login_dialog, null); final EditText password = view.findViewById(R.id.password); + if (!pin) + { + EditText username = view.findViewById(R.id.username); + username.setText(profileInfo.getString(VpnProfileDataSource.KEY_USERNAME)); + } AlertDialog.Builder adb = new AlertDialog.Builder(getActivity()); adb.setView(view); - adb.setTitle(getString(R.string.login_title)); + adb.setTitle(getString(pin ? R.string.login_title_pin : R.string.login_title)); adb.setPositiveButton(R.string.login_confirm, (dialog, which) -> mListener.onLoginDialogDismissed(password.getText().toString().trim())); adb.setNegativeButton(android.R.string.cancel, (dialog, which) -> diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_creds.c b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_creds.c index 63e97e155c..3464a85cf6 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_creds.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_creds.c @@ -263,7 +263,7 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, } else { - pwd = charonservice->get_password(charonservice); + pwd = charonservice->get_password(charonservice, type == SHARED_PIN); if (pwd) { shared = shared_key_create(type, chunk_clone(chunk_from_str(pwd))); diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c index 4fe0289bb2..b1bc625d16 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c @@ -391,7 +391,7 @@ failed: } METHOD(charonservice_t, get_password, char*, - private_charonservice_t *this) + private_charonservice_t *this, bool pin) { JNIEnv *env; jmethodID method_id; @@ -401,12 +401,13 @@ METHOD(charonservice_t, get_password, char*, androidjni_attach_thread(&env); method_id = (*env)->GetMethodID(env, android_charonvpnservice_class, - "getPassword", "()Ljava/lang/String;"); + "getPassword", "(Z)Ljava/lang/String;"); if (!method_id) { goto failed; } - jpassword = (*env)->CallObjectMethod(env, this->vpn_service, method_id); + jpassword = (*env)->CallObjectMethod(env, this->vpn_service, method_id, + pin); if (androidjni_exception_occurred(env) || !jpassword) { goto failed; diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.h b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.h index d835b50406..09dcb9520e 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.h +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.h @@ -146,9 +146,10 @@ struct charonservice_t { /** * Get a password from the user via JNI * + * @param pin whether to request a PIN instead of a password * @return allocated password, NULL on failure */ - char *(*get_password)(charonservice_t *this); + char *(*get_password)(charonservice_t *this, bool pin); /** * Get the current vpnservice_builder_t object diff --git a/src/frontends/android/app/src/main/res/layout/login_dialog_pin.xml b/src/frontends/android/app/src/main/res/layout/login_dialog_pin.xml new file mode 100644 index 0000000000..0e79ab7fa8 --- /dev/null +++ b/src/frontends/android/app/src/main/res/layout/login_dialog_pin.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + diff --git a/src/frontends/android/app/src/main/res/values-de/strings.xml b/src/frontends/android/app/src/main/res/values-de/strings.xml index 687befe8a1..e0af48bfac 100644 --- a/src/frontends/android/app/src/main/res/values-de/strings.xml +++ b/src/frontends/android/app/src/main/res/values-de/strings.xml @@ -34,6 +34,7 @@ VPN Passwort Wird verwendet, um vom Benutzer ein Passwort zu verlangen. Password benötigt + PIN benötigt Einstellungen @@ -195,9 +196,11 @@ Korrekturanweisungen - Passwort eingeben um zu verbinden + Passwort eingeben, um zu verbinden + PIN eingeben, um zu verbinden Benutzername Passwort + PIN Verbinden Fehler beim Aufsetzen des VPN: %1$s. Server-Adresse konnte nicht aufgelöst werden diff --git a/src/frontends/android/app/src/main/res/values-pl/strings.xml b/src/frontends/android/app/src/main/res/values-pl/strings.xml index dbb06f9aff..66b10957f7 100644 --- a/src/frontends/android/app/src/main/res/values-pl/strings.xml +++ b/src/frontends/android/app/src/main/res/values-pl/strings.xml @@ -34,6 +34,7 @@ VPN password Used to request a password from the user. Password required + PIN required Settings @@ -196,8 +197,10 @@ Wprowadż hasło + Enter PIN to connect Użytkownik Hasło + PIN Połącz Nie udało się utworzyć tunelu VPN: %1$s. Nie znaleziono adresu serwer diff --git a/src/frontends/android/app/src/main/res/values-ru/strings.xml b/src/frontends/android/app/src/main/res/values-ru/strings.xml index f4925f5ec2..47947128af 100644 --- a/src/frontends/android/app/src/main/res/values-ru/strings.xml +++ b/src/frontends/android/app/src/main/res/values-ru/strings.xml @@ -31,6 +31,7 @@ VPN password Used to request a password from the user. Password required + PIN required Settings @@ -193,8 +194,10 @@ Введите пароль для соединения + Enter PIN to connect Логин Пароль + PIN Соединить Ошибка подключения к VPN: %1$s. Не найден адрес сервер diff --git a/src/frontends/android/app/src/main/res/values-ua/strings.xml b/src/frontends/android/app/src/main/res/values-ua/strings.xml index 45ded7841c..13d51a3071 100644 --- a/src/frontends/android/app/src/main/res/values-ua/strings.xml +++ b/src/frontends/android/app/src/main/res/values-ua/strings.xml @@ -32,6 +32,7 @@ VPN password Used to request a password from the user. Password required + PIN required Settings @@ -194,8 +195,10 @@ Введіть пароль для з\'єднання + Enter PIN to connect Логін Пароль + PIN Підключити Помилка підлючення VPN: %1$s. Помилка пошуку адреси сервер diff --git a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml index cdb6f79c3b..bc433d3b90 100644 --- a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml @@ -31,6 +31,7 @@ VPN password Used to request a password from the user. Password required + PIN required Settings @@ -193,8 +194,10 @@ 输入密码用于连接 + Enter PIN to connect 用户名 密码 + PIN 连接 无法建立VPN:%1$s。 服务器地址查找失败 diff --git a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml index 51759fc50a..ff6136f322 100644 --- a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml @@ -31,6 +31,7 @@ VPN password Used to request a password from the user. Password required + PIN required Settings @@ -193,8 +194,10 @@ 輸入密碼進行連線 + Enter PIN to connect 用戶名稱 密碼 + PIN 連線 無法建立VPN:%1$s。 伺服器位置查詢失敗 diff --git a/src/frontends/android/app/src/main/res/values/strings.xml b/src/frontends/android/app/src/main/res/values/strings.xml index 22d496bb4c..348cea1655 100644 --- a/src/frontends/android/app/src/main/res/values/strings.xml +++ b/src/frontends/android/app/src/main/res/values/strings.xml @@ -34,6 +34,7 @@ VPN password Used to request a password from the user. Password required + PIN required Settings @@ -196,8 +197,10 @@ Enter password to connect + Enter PIN to connect Username Password + PIN Connect Failed to establish VPN: %1$s. Server address lookup failed -- 2.47.2