android: Show an error if client certificate is unavailable

This can happen on systems (e.g. Android 7.x) where Always-on VPNs are
triggered right after booting before the KeyChain is unlocked by the user.
Retrieving the certificate chain or private key then fails with
"KeyChainException: IllegalStateException: keystore is LOCKED" until the
user unlocks the screen once.

The built-in client actually also fails in this situation (e.g. with XAuth
RSA), it tries three times then stops and shows an error notification.
This commit is contained in:
Tobias Brunner 2018-06-14 15:20:57 +02:00
parent f0b3e303c4
commit ab5dbbc4ab
11 changed files with 17 additions and 3 deletions

View File

@ -128,7 +128,8 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
static final int STATE_PEER_AUTH_ERROR = 4;
static final int STATE_LOOKUP_ERROR = 5;
static final int STATE_UNREACHABLE_ERROR = 6;
static final int STATE_GENERIC_ERROR = 7;
static final int STATE_CERTIFICATE_UNAVAILABLE = 7;
static final int STATE_GENERIC_ERROR = 8;
@Override
public int onStartCommand(Intent intent, int flags, int startId)
@ -589,6 +590,9 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
case STATE_UNREACHABLE_ERROR:
setErrorDisconnect(ErrorState.UNREACHABLE);
break;
case STATE_CERTIFICATE_UNAVAILABLE:
setErrorDisconnect(ErrorState.CERTIFICATE_UNAVAILABLE);
break;
case STATE_GENERIC_ERROR:
setErrorDisconnect(ErrorState.GENERIC_ERROR);
break;
@ -707,7 +711,6 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
* @return the private key
* @throws InterruptedException
* @throws KeyChainException
* @throws CertificateEncodingException
*/
private PrivateKey getUserKey() throws KeyChainException, InterruptedException
{

View File

@ -62,6 +62,7 @@ public class VpnStateService extends Service
UNREACHABLE,
GENERIC_ERROR,
PASSWORD_MISSING,
CERTIFICATE_UNAVAILABLE,
}
/**
@ -194,6 +195,8 @@ public class VpnStateService extends Service
return R.string.error_unreachable;
case PASSWORD_MISSING:
return R.string.error_password_missing;
case CERTIFICATE_UNAVAILABLE:
return R.string.error_certificate_unavailable;
default:
return R.string.error_generic;
}

View File

@ -794,7 +794,7 @@ static job_requeue_t initiate(private_android_service_t *this)
{
peer_cfg->destroy(peer_cfg);
charonservice->update_status(charonservice,
CHARONSERVICE_GENERIC_ERROR);
CHARONSERVICE_CERTIFICATE_UNAVAILABLE);
return JOB_REQUEUE_NONE;
}
}

View File

@ -59,6 +59,7 @@ enum android_vpn_state_t {
CHARONSERVICE_PEER_AUTH_ERROR,
CHARONSERVICE_LOOKUP_ERROR,
CHARONSERVICE_UNREACHABLE_ERROR,
CHARONSERVICE_CERTIFICATE_UNAVAILABLE,
CHARONSERVICE_GENERIC_ERROR,
};

View File

@ -188,6 +188,7 @@
<string name="error_assessment_failed">Sicherheitsassessment ist fehlgeschlagen</string>
<string name="error_generic">Unbekannter Fehler während des Verbindens</string>
<string name="error_password_missing">Passwort nicht verfügbar</string>
<string name="error_certificate_unavailable">Benutzer-Zertifikat nicht verfügbar</string>
<string name="vpn_connected">VPN verbunden</string>
<string name="vpn_profile_connected">Dieses VPN Profil ist momentan verbunden!</string>
<string name="reconnect">Neu verbinden</string>

View File

@ -188,6 +188,7 @@
<string name="error_assessment_failed">Security assessment failed</string>
<string name="error_generic">Nieznany błąd w czasie połączenia</string>
<string name="error_password_missing">Password unavailable</string>
<string name="error_certificate_unavailable">Client certificate unavailable</string>
<string name="vpn_connected">Połączenie z VPN</string>
<string name="vpn_profile_connected">Ten profil VPN jest obecnie połaczony!</string>
<string name="reconnect">Połączyć ponownie</string>

View File

@ -185,6 +185,7 @@
<string name="error_assessment_failed">Security assessment failed</string>
<string name="error_generic">Неизвестная ошибка</string>
<string name="error_password_missing">Password unavailable</string>
<string name="error_certificate_unavailable">Client certificate unavailable</string>
<string name="vpn_connected">Соединение с VPN установлено</string>
<string name="vpn_profile_connected">Подключение к этому профилю VPN уже существует!</string>
<string name="reconnect">Переподключить</string>

View File

@ -186,6 +186,7 @@
<string name="error_assessment_failed">Security assessment failed</string>
<string name="error_generic">Невідома помилка під час підключення</string>
<string name="error_password_missing">Password unavailable</string>
<string name="error_certificate_unavailable">Client certificate unavailable</string>
<string name="vpn_connected">VPN підключено</string>
<string name="vpn_profile_connected">Цей VPN профіль зараз підключений!</string>
<string name="reconnect">Перепідключитися</string>

View File

@ -185,6 +185,7 @@
<string name="error_assessment_failed">可靠性评估失败</string>
<string name="error_generic">连接中遭遇未知失败</string>
<string name="error_password_missing">Password unavailable</string>
<string name="error_certificate_unavailable">Client certificate unavailable</string>
<string name="vpn_connected">VPN已连接</string>
<string name="vpn_profile_connected">此VPN配置目前已连接。</string>
<string name="reconnect">重连</string>

View File

@ -185,6 +185,7 @@
<string name="error_assessment_failed">穩定性評估失敗</string>
<string name="error_generic">連線中遇到不明錯誤</string>
<string name="error_password_missing">Password unavailable</string>
<string name="error_certificate_unavailable">Client certificate unavailable</string>
<string name="vpn_connected">VPN已連線</string>
<string name="vpn_profile_connected">這個VPN設定檔目前已經連線。</string>
<string name="reconnect">重新連線</string>

View File

@ -188,6 +188,7 @@
<string name="error_assessment_failed">Security assessment failed</string>
<string name="error_generic">Unspecified failure while connecting</string>
<string name="error_password_missing">Password unavailable</string>
<string name="error_certificate_unavailable">Client certificate unavailable</string>
<string name="vpn_connected">VPN connected</string>
<string name="vpn_profile_connected">This VPN profile is currently connected!</string>
<string name="reconnect">Reconnect</string>