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) { | ||||||
|  | 				try { | ||||||
| 					callback.onIqPacketReceived(account, packet); | 					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 New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch