unified all account state exceptions
This commit is contained in:
parent
404cf808b0
commit
7b6d49f329
|
@ -118,9 +118,11 @@ public class Account extends AbstractEntity {
|
||||||
REGISTRATION_CONFLICT(true),
|
REGISTRATION_CONFLICT(true),
|
||||||
REGISTRATION_SUCCESSFUL,
|
REGISTRATION_SUCCESSFUL,
|
||||||
REGISTRATION_NOT_SUPPORTED(true),
|
REGISTRATION_NOT_SUPPORTED(true),
|
||||||
SECURITY_ERROR(true),
|
TLS_ERROR(true),
|
||||||
INCOMPATIBLE_SERVER(true),
|
INCOMPATIBLE_SERVER(true),
|
||||||
TOR_NOT_AVAILABLE(true),
|
TOR_NOT_AVAILABLE(true),
|
||||||
|
DOWNGRADE_ATTACK(true),
|
||||||
|
SESSION_FAILURE(true),
|
||||||
BIND_FAILURE(true),
|
BIND_FAILURE(true),
|
||||||
HOST_UNKNOWN(true),
|
HOST_UNKNOWN(true),
|
||||||
REGISTRATION_PLEASE_WAIT(true),
|
REGISTRATION_PLEASE_WAIT(true),
|
||||||
|
@ -168,14 +170,18 @@ public class Account extends AbstractEntity {
|
||||||
return R.string.account_status_regis_success;
|
return R.string.account_status_regis_success;
|
||||||
case REGISTRATION_NOT_SUPPORTED:
|
case REGISTRATION_NOT_SUPPORTED:
|
||||||
return R.string.account_status_regis_not_sup;
|
return R.string.account_status_regis_not_sup;
|
||||||
case SECURITY_ERROR:
|
case TLS_ERROR:
|
||||||
return R.string.account_status_security_error;
|
return R.string.account_status_tls_error;
|
||||||
case INCOMPATIBLE_SERVER:
|
case INCOMPATIBLE_SERVER:
|
||||||
return R.string.account_status_incompatible_server;
|
return R.string.account_status_incompatible_server;
|
||||||
case TOR_NOT_AVAILABLE:
|
case TOR_NOT_AVAILABLE:
|
||||||
return R.string.account_status_tor_unavailable;
|
return R.string.account_status_tor_unavailable;
|
||||||
case BIND_FAILURE:
|
case BIND_FAILURE:
|
||||||
return R.string.account_status_bind_failure;
|
return R.string.account_status_bind_failure;
|
||||||
|
case SESSION_FAILURE:
|
||||||
|
return R.string.session_failure;
|
||||||
|
case DOWNGRADE_ATTACK:
|
||||||
|
return R.string.downgrade_attack;
|
||||||
case HOST_UNKNOWN:
|
case HOST_UNKNOWN:
|
||||||
return R.string.account_status_host_unknown;
|
return R.string.account_status_host_unknown;
|
||||||
case POLICY_VIOLATION:
|
case POLICY_VIOLATION:
|
||||||
|
|
|
@ -4,5 +4,5 @@ import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
|
||||||
public interface OnIqPacketReceived extends PacketReceived {
|
public interface OnIqPacketReceived extends PacketReceived {
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet);
|
void onIqPacketReceived(Account account, IqPacket packet);
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,7 +299,7 @@ public class XmppConnection implements Runnable {
|
||||||
final SSLSession session = ((SSLSocket) localSocket).getSession();
|
final SSLSession session = ((SSLSocket) localSocket).getSession();
|
||||||
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), session)) {
|
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), session)) {
|
||||||
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
|
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
|
||||||
throw new SecurityException();
|
throw new StateChangingException(Account.State.TLS_ERROR);
|
||||||
}
|
}
|
||||||
} catch (KeyManagementException e) {
|
} catch (KeyManagementException e) {
|
||||||
features.encryptionEnabled = false;
|
features.encryptionEnabled = false;
|
||||||
|
@ -388,7 +388,7 @@ public class XmppConnection implements Runnable {
|
||||||
|
|
||||||
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), ((SSLSocket) localSocket).getSession())) {
|
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), ((SSLSocket) localSocket).getSession())) {
|
||||||
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
|
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
|
||||||
throw new SecurityException();
|
throw new StateChangingException(Account.State.TLS_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (startXmpp(localSocket)) {
|
if (startXmpp(localSocket)) {
|
||||||
|
@ -396,7 +396,7 @@ public class XmppConnection implements Runnable {
|
||||||
} else {
|
} else {
|
||||||
localSocket.close();
|
localSocket.close();
|
||||||
}
|
}
|
||||||
} catch (final SecurityException e) {
|
} catch (final StateChangingException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": thread was interrupted before beginning stream");
|
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": thread was interrupted before beginning stream");
|
||||||
|
@ -410,28 +410,14 @@ public class XmppConnection implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
processStream();
|
processStream();
|
||||||
} catch (final java.lang.SecurityException e) {
|
|
||||||
this.changeStatus(Account.State.MISSING_INTERNET_PERMISSION);
|
|
||||||
} catch (final RegistrationNotSupportedException e) {
|
|
||||||
this.changeStatus(Account.State.REGISTRATION_NOT_SUPPORTED);
|
|
||||||
} catch (final IncompatibleServerException e) {
|
|
||||||
this.changeStatus(Account.State.INCOMPATIBLE_SERVER);
|
|
||||||
} catch (final SecurityException e) {
|
} catch (final SecurityException e) {
|
||||||
this.changeStatus(Account.State.SECURITY_ERROR);
|
this.changeStatus(Account.State.MISSING_INTERNET_PERMISSION);
|
||||||
} catch (final UnauthorizedException e) {
|
} catch(final StateChangingException e) {
|
||||||
this.changeStatus(Account.State.UNAUTHORIZED);
|
this.changeStatus(e.state);
|
||||||
} catch (final PaymentRequiredException e) {
|
|
||||||
this.changeStatus(Account.State.PAYMENT_REQUIRED);
|
|
||||||
} catch (final UnknownHostException | ConnectException e) {
|
} catch (final UnknownHostException | ConnectException e) {
|
||||||
this.changeStatus(Account.State.SERVER_NOT_FOUND);
|
this.changeStatus(Account.State.SERVER_NOT_FOUND);
|
||||||
} catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
|
} catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
|
||||||
this.changeStatus(Account.State.TOR_NOT_AVAILABLE);
|
this.changeStatus(Account.State.TOR_NOT_AVAILABLE);
|
||||||
} catch(final StreamErrorHostUnknown e) {
|
|
||||||
this.changeStatus(Account.State.HOST_UNKNOWN);
|
|
||||||
} catch(final StreamErrorPolicyViolation e) {
|
|
||||||
this.changeStatus(Account.State.POLICY_VIOLATION);
|
|
||||||
} catch(final StreamError e) {
|
|
||||||
this.changeStatus(Account.State.STREAM_ERROR);
|
|
||||||
} catch (final IOException | XmlPullParserException | NoSuchAlgorithmException e) {
|
} catch (final IOException | XmlPullParserException | NoSuchAlgorithmException e) {
|
||||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
|
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
|
||||||
this.changeStatus(Account.State.OFFLINE);
|
this.changeStatus(Account.State.OFFLINE);
|
||||||
|
@ -528,8 +514,8 @@ public class XmppConnection implements Runnable {
|
||||||
try {
|
try {
|
||||||
saslMechanism.getResponse(challenge);
|
saslMechanism.getResponse(challenge);
|
||||||
} catch (final SaslMechanism.AuthenticationException e) {
|
} catch (final SaslMechanism.AuthenticationException e) {
|
||||||
disconnect(true);
|
|
||||||
Log.e(Config.LOGTAG, String.valueOf(e));
|
Log.e(Config.LOGTAG, String.valueOf(e));
|
||||||
|
throw new StateChangingException(Account.State.UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": logged in");
|
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": logged in");
|
||||||
account.setKey(Account.PINNED_MECHANISM_KEY,
|
account.setKey(Account.PINNED_MECHANISM_KEY,
|
||||||
|
@ -551,9 +537,9 @@ public class XmppConnection implements Runnable {
|
||||||
&& text.contains("renew")
|
&& text.contains("renew")
|
||||||
&& Config.MAGIC_CREATE_DOMAIN != null
|
&& Config.MAGIC_CREATE_DOMAIN != null
|
||||||
&& text.contains(Config.MAGIC_CREATE_DOMAIN)) {
|
&& text.contains(Config.MAGIC_CREATE_DOMAIN)) {
|
||||||
throw new PaymentRequiredException();
|
throw new StateChangingException(Account.State.PAYMENT_REQUIRED);
|
||||||
} else {
|
} else {
|
||||||
throw new UnauthorizedException();
|
throw new StateChangingException(Account.State.UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
} else if (nextTag.isStart("challenge")) {
|
} else if (nextTag.isStart("challenge")) {
|
||||||
final String challenge = tagReader.readElement(nextTag).getContent();
|
final String challenge = tagReader.readElement(nextTag).getContent();
|
||||||
|
@ -776,7 +762,11 @@ public class XmppConnection implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.onIqPacketReceived(account,packet);
|
try {
|
||||||
|
callback.onIqPacketReceived(account, packet);
|
||||||
|
} catch (StateChangingError error) {
|
||||||
|
throw new StateChangingException(error.state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -819,7 +809,7 @@ public class XmppConnection implements Runnable {
|
||||||
|
|
||||||
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), sslSocket.getSession())) {
|
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), sslSocket.getSession())) {
|
||||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
|
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
|
||||||
throw new SecurityException();
|
throw new StateChangingException(Account.State.TLS_ERROR);
|
||||||
}
|
}
|
||||||
tagReader.setInputStream(sslSocket.getInputStream());
|
tagReader.setInputStream(sslSocket.getInputStream());
|
||||||
tagWriter.setOutputStream(sslSocket.getOutputStream());
|
tagWriter.setOutputStream(sslSocket.getOutputStream());
|
||||||
|
@ -835,7 +825,7 @@ public class XmppConnection implements Runnable {
|
||||||
sslSocket.close();
|
sslSocket.close();
|
||||||
} catch (final NoSuchAlgorithmException | KeyManagementException e1) {
|
} catch (final NoSuchAlgorithmException | KeyManagementException e1) {
|
||||||
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
|
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
|
||||||
throw new SecurityException();
|
throw new StateChangingException(Account.State.TLS_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,10 +838,10 @@ public class XmppConnection implements Runnable {
|
||||||
if (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS) {
|
if (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS) {
|
||||||
sendRegistryRequest();
|
sendRegistryRequest();
|
||||||
} else {
|
} else {
|
||||||
throw new IncompatibleServerException();
|
throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
|
||||||
}
|
}
|
||||||
} else if (!this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) {
|
} else if (!this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) {
|
||||||
throw new RegistrationNotSupportedException();
|
throw new StateChangingException(Account.State.REGISTRATION_NOT_SUPPORTED);
|
||||||
} else if (this.streamFeatures.hasChild("mechanisms")
|
} else if (this.streamFeatures.hasChild("mechanisms")
|
||||||
&& shouldAuthenticate
|
&& shouldAuthenticate
|
||||||
&& (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS)) {
|
&& (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS)) {
|
||||||
|
@ -868,7 +858,7 @@ public class XmppConnection implements Runnable {
|
||||||
if (this.streamFeatures.hasChild("bind")) {
|
if (this.streamFeatures.hasChild("bind")) {
|
||||||
sendBindRequest();
|
sendBindRequest();
|
||||||
} else {
|
} else {
|
||||||
throw new IncompatibleServerException();
|
throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,7 +888,7 @@ public class XmppConnection implements Runnable {
|
||||||
" has lower priority (" + String.valueOf(saslMechanism.getPriority()) +
|
" has lower priority (" + String.valueOf(saslMechanism.getPriority()) +
|
||||||
") than pinned priority (" + pinnedMechanism +
|
") than pinned priority (" + pinnedMechanism +
|
||||||
"). Possible downgrade attack?");
|
"). Possible downgrade attack?");
|
||||||
throw new SecurityException();
|
throw new StateChangingException(Account.State.DOWNGRADE_ATTACK);
|
||||||
}
|
}
|
||||||
Log.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism());
|
Log.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism());
|
||||||
auth.setAttribute("mechanism", saslMechanism.getMechanism());
|
auth.setAttribute("mechanism", saslMechanism.getMechanism());
|
||||||
|
@ -907,7 +897,7 @@ public class XmppConnection implements Runnable {
|
||||||
}
|
}
|
||||||
tagWriter.writeElement(auth);
|
tagWriter.writeElement(auth);
|
||||||
} else {
|
} else {
|
||||||
throw new IncompatibleServerException();
|
throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,8 +1032,7 @@ public class XmppConnection implements Runnable {
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure (" + packet.toString());
|
Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure (" + packet.toString());
|
||||||
}
|
}
|
||||||
forceCloseSocket();
|
throw new StateChangingError(Account.State.BIND_FAILURE);
|
||||||
changeStatus(Account.State.BIND_FAILURE);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1085,8 +1074,7 @@ public class XmppConnection implements Runnable {
|
||||||
if (packet.getType() == IqPacket.TYPE.RESULT) {
|
if (packet.getType() == IqPacket.TYPE.RESULT) {
|
||||||
sendPostBindInitialization();
|
sendPostBindInitialization();
|
||||||
} else if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
|
} else if (packet.getType() != IqPacket.TYPE.TIMEOUT) {
|
||||||
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not init sessions");
|
throw new StateChangingError(Account.State.SESSION_FAILURE);
|
||||||
disconnect(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1266,12 +1254,12 @@ public class XmppConnection implements Runnable {
|
||||||
+ account.getResource() + ")");
|
+ account.getResource() + ")");
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
} else if (streamError.hasChild("host-unknown")) {
|
} else if (streamError.hasChild("host-unknown")) {
|
||||||
throw new StreamErrorHostUnknown();
|
throw new StateChangingException(Account.State.HOST_UNKNOWN);
|
||||||
} else if (streamError.hasChild("policy-violation")) {
|
} else if (streamError.hasChild("policy-violation")) {
|
||||||
throw new StreamErrorPolicyViolation();
|
throw new StateChangingException(Account.State.POLICY_VIOLATION);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString());
|
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": stream error "+streamError.toString());
|
||||||
throw new StreamError();
|
throw new StateChangingException(Account.State.STREAM_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1561,36 +1549,20 @@ public class XmppConnection implements Runnable {
|
||||||
return Identity.UNKNOWN;
|
return Identity.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UnauthorizedException extends IOException {
|
private class StateChangingError extends Error {
|
||||||
|
private final Account.State state;
|
||||||
|
|
||||||
|
public StateChangingError(Account.State state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SecurityException extends IOException {
|
private class StateChangingException extends IOException {
|
||||||
|
private final Account.State state;
|
||||||
|
|
||||||
|
public StateChangingException(Account.State state) {
|
||||||
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IncompatibleServerException extends IOException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class StreamErrorHostUnknown extends StreamError {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class StreamErrorPolicyViolation extends StreamError {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class StreamError extends IOException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class PaymentRequiredException extends IOException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RegistrationNotSupportedException extends IOException {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Identity {
|
public enum Identity {
|
||||||
|
|
|
@ -158,7 +158,7 @@
|
||||||
<string name="account_status_regis_conflict">Username already in use</string>
|
<string name="account_status_regis_conflict">Username already in use</string>
|
||||||
<string name="account_status_regis_success">Registration completed</string>
|
<string name="account_status_regis_success">Registration completed</string>
|
||||||
<string name="account_status_regis_not_sup">Server does not support registration</string>
|
<string name="account_status_regis_not_sup">Server does not support registration</string>
|
||||||
<string name="account_status_security_error">Security error</string>
|
<string name="account_status_tls_error">TLS error</string>
|
||||||
<string name="account_status_policy_violation">Policy violation</string>
|
<string name="account_status_policy_violation">Policy violation</string>
|
||||||
<string name="account_status_incompatible_server">Incompatible server</string>
|
<string name="account_status_incompatible_server">Incompatible server</string>
|
||||||
<string name="account_status_stream_error">Stream error</string>
|
<string name="account_status_stream_error">Stream error</string>
|
||||||
|
@ -747,4 +747,6 @@
|
||||||
<string name="block_entire_domain">Block entire domain</string>
|
<string name="block_entire_domain">Block entire domain</string>
|
||||||
<string name="online_right_now">online right now</string>
|
<string name="online_right_now">online right now</string>
|
||||||
<string name="retry_decryption">Retry decryption</string>
|
<string name="retry_decryption">Retry decryption</string>
|
||||||
|
<string name="session_failure">Session failure</string>
|
||||||
|
<string name="downgrade_attack">Downgrade attack</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue