Introduce SmackSaslException

This commit is contained in:
Florian Schmaus 2019-02-10 19:50:46 +01:00
parent bb759a136e
commit b51a6c54e8
12 changed files with 161 additions and 100 deletions

View File

@ -32,6 +32,8 @@ import javax.net.ssl.SSLSession;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.packet.Mechanisms; import org.jivesoftware.smack.packet.Mechanisms;
import org.jivesoftware.smack.sasl.SASLErrorException; import org.jivesoftware.smack.sasl.SASLErrorException;
@ -184,12 +186,14 @@ public final class SASLAuthentication {
* @throws XMPPErrorException * @throws XMPPErrorException
* @throws SASLErrorException * @throws SASLErrorException
* @throws IOException * @throws IOException
* @throws SmackException
* @throws InterruptedException * @throws InterruptedException
* @throws SmackSaslException
* @throws NotConnectedException
* @throws NoResponseException
*/ */
public SASLMechanism authenticate(String username, String password, EntityBareJid authzid, SSLSession sslSession) public SASLMechanism authenticate(String username, String password, EntityBareJid authzid, SSLSession sslSession)
throws XMPPErrorException, SASLErrorException, IOException, throws XMPPErrorException, SASLErrorException, IOException,
SmackException, InterruptedException { InterruptedException, SmackSaslException, NotConnectedException, NoResponseException {
currentMechanism = selectMechanism(authzid); currentMechanism = selectMechanism(authzid);
final CallbackHandler callbackHandler = configuration.getCallbackHandler(); final CallbackHandler callbackHandler = configuration.getCallbackHandler();
final String host = connection.getHost(); final String host = connection.getHost();
@ -212,10 +216,12 @@ public final class SASLAuthentication {
} }
if (saslException != null) { if (saslException != null) {
if (saslException instanceof SmackException) { if (saslException instanceof SmackSaslException) {
throw (SmackException) saslException; throw (SmackSaslException) saslException;
} else if (saslException instanceof SASLErrorException) { } else if (saslException instanceof SASLErrorException) {
throw (SASLErrorException) saslException; throw (SASLErrorException) saslException;
} else if (saslException instanceof NotConnectedException) {
throw (NotConnectedException) saslException;
} else { } else {
throw new IllegalStateException("Unexpected exception type" , saslException); throw new IllegalStateException("Unexpected exception type" , saslException);
} }
@ -248,13 +254,14 @@ public final class SASLAuthentication {
* *
* @param challenge a base64 encoded string representing the challenge. * @param challenge a base64 encoded string representing the challenge.
* @param finalChallenge true if this is the last challenge send by the server within the success stanza * @param finalChallenge true if this is the last challenge send by the server within the success stanza
* @throws SmackException * @throws SmackSaslException
* @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
public void challengeReceived(String challenge, boolean finalChallenge) throws SmackException, InterruptedException { public void challengeReceived(String challenge, boolean finalChallenge) throws SmackSaslException, NotConnectedException, InterruptedException {
try { try {
currentMechanism.challengeReceived(challenge, finalChallenge); currentMechanism.challengeReceived(challenge, finalChallenge);
} catch (InterruptedException | SmackException e) { } catch (InterruptedException | SmackSaslException | NotConnectedException e) {
authenticationFailed(e); authenticationFailed(e);
throw e; throw e;
} }
@ -325,7 +332,7 @@ public final class SASLAuthentication {
return lastUsedMech.getName(); return lastUsedMech.getName();
} }
private SASLMechanism selectMechanism(EntityBareJid authzid) throws SmackException { private SASLMechanism selectMechanism(EntityBareJid authzid) throws SmackException.SmackSaslException {
Iterator<SASLMechanism> it = REGISTERED_MECHANISMS.iterator(); Iterator<SASLMechanism> it = REGISTERED_MECHANISMS.iterator();
final List<String> serverMechanisms = getServerMechanisms(); final List<String> serverMechanisms = getServerMechanisms();
if (serverMechanisms.isEmpty()) { if (serverMechanisms.isEmpty()) {
@ -357,7 +364,7 @@ public final class SASLAuthentication {
synchronized (BLACKLISTED_MECHANISMS) { synchronized (BLACKLISTED_MECHANISMS) {
// @formatter:off // @formatter:off
throw new SmackException( throw new SmackException.SmackSaslException(
"No supported and enabled SASL Mechanism provided by server. " + "No supported and enabled SASL Mechanism provided by server. " +
"Server announced mechanisms: " + serverMechanisms + ". " + "Server announced mechanisms: " + serverMechanisms + ". " +
"Registered SASL mechanisms with Smack: " + REGISTERED_MECHANISMS + ". " + "Registered SASL mechanisms with Smack: " + REGISTERED_MECHANISMS + ". " +

View File

@ -368,4 +368,24 @@ public class SmackException extends Exception {
super(exception); super(exception);
} }
} }
public static class SmackSaslException extends SmackException {
/**
*
*/
private static final long serialVersionUID = 1L;
public SmackSaslException(Exception exception) {
super(exception);
}
public SmackSaslException(String message) {
super(message);
}
public SmackSaslException(String message, Exception exception) {
super(message, exception);
}
}
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2003-2007 Jive Software, 2014-2018 Florian Schmaus * Copyright 2003-2007 Jive Software, 2014-2019 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,8 +23,8 @@ import javax.net.ssl.SSLSession;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.AuthMechanism; import org.jivesoftware.smack.sasl.packet.SaslStreamElements.AuthMechanism;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Response; import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Response;
@ -139,13 +139,13 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
* @param password the password for this account. * @param password the password for this account.
* @param authzid the optional authorization identity. * @param authzid the optional authorization identity.
* @param sslSession the optional SSL/TLS session (if one was established) * @param sslSession the optional SSL/TLS session (if one was established)
* @throws SmackException If a network error occurs while authenticating. * @throws SmackSaslException if a SASL related error occurs.
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
public final void authenticate(String username, String host, DomainBareJid serviceName, String password, public final void authenticate(String username, String host, DomainBareJid serviceName, String password,
EntityBareJid authzid, SSLSession sslSession) EntityBareJid authzid, SSLSession sslSession)
throws SmackException, NotConnectedException, InterruptedException { throws SmackSaslException, NotConnectedException, InterruptedException {
this.authenticationId = username; this.authenticationId = username;
this.host = host; this.host = host;
this.serviceName = serviceName; this.serviceName = serviceName;
@ -157,10 +157,7 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
authenticate(); authenticate();
} }
/** protected void authenticateInternal() throws SmackSaslException {
* @throws SmackException
*/
protected void authenticateInternal() throws SmackException {
} }
/** /**
@ -172,12 +169,12 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
* @param cbh the CallbackHandler to obtain user information. * @param cbh the CallbackHandler to obtain user information.
* @param authzid the optional authorization identity. * @param authzid the optional authorization identity.
* @param sslSession the optional SSL/TLS session (if one was established) * @param sslSession the optional SSL/TLS session (if one was established)
* @throws SmackException * @throws SmackSaslException if a SASL related error occurs.
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
public void authenticate(String host, DomainBareJid serviceName, CallbackHandler cbh, EntityBareJid authzid, SSLSession sslSession) public void authenticate(String host, DomainBareJid serviceName, CallbackHandler cbh, EntityBareJid authzid, SSLSession sslSession)
throws SmackException, NotConnectedException, InterruptedException { throws SmackSaslException, NotConnectedException, InterruptedException {
this.host = host; this.host = host;
this.serviceName = serviceName; this.serviceName = serviceName;
this.authorizationId = authzid; this.authorizationId = authzid;
@ -187,9 +184,9 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
authenticate(); authenticate();
} }
protected abstract void authenticateInternal(CallbackHandler cbh) throws SmackException; protected abstract void authenticateInternal(CallbackHandler cbh) throws SmackSaslException;
private void authenticate() throws SmackException, NotConnectedException, InterruptedException { private void authenticate() throws SmackSaslException, NotConnectedException, InterruptedException {
byte[] authenticationBytes = getAuthenticationText(); byte[] authenticationBytes = getAuthenticationText();
String authenticationText; String authenticationText;
// Some SASL mechanisms do return an empty array (e.g. EXTERNAL from javax), so check that // Some SASL mechanisms do return an empty array (e.g. EXTERNAL from javax), so check that
@ -213,9 +210,9 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
* empty array here. * empty array here.
* *
* @return the initial response or null * @return the initial response or null
* @throws SmackException * @throws SmackSaslException
*/ */
protected abstract byte[] getAuthenticationText() throws SmackException; protected abstract byte[] getAuthenticationText() throws SmackSaslException;
/** /**
* The server is challenging the SASL mechanism for the stanza he just sent. Send a * The server is challenging the SASL mechanism for the stanza he just sent. Send a
@ -223,10 +220,11 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
* *
* @param challengeString a base64 encoded string representing the challenge. * @param challengeString a base64 encoded string representing the challenge.
* @param finalChallenge true if this is the last challenge send by the server within the success stanza * @param finalChallenge true if this is the last challenge send by the server within the success stanza
* @throws SmackException exception * @throws SmackSaslException if a SASL related error occurs.
* @throws InterruptedException if the connection is interrupted * @throws InterruptedException if the connection is interrupted
* @throws NotConnectedException
*/ */
public final void challengeReceived(String challengeString, boolean finalChallenge) throws SmackException, InterruptedException { public final void challengeReceived(String challengeString, boolean finalChallenge) throws SmackSaslException, InterruptedException, NotConnectedException {
byte[] challenge = Base64.decode((challengeString != null && challengeString.equals("=")) ? "" : challengeString); byte[] challenge = Base64.decode((challengeString != null && challengeString.equals("=")) ? "" : challengeString);
byte[] response = evaluateChallenge(challenge); byte[] response = evaluateChallenge(challenge);
if (finalChallenge) { if (finalChallenge) {
@ -251,9 +249,9 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
* @param challenge challenge to evaluate. * @param challenge challenge to evaluate.
* *
* @return null. * @return null.
* @throws SmackException in case of an error. * @throws SmackSaslException If a SASL related error occurs.
*/ */
protected byte[] evaluateChallenge(byte[] challenge) throws SmackException { protected byte[] evaluateChallenge(byte[] challenge) throws SmackSaslException {
return null; return null;
} }
@ -278,7 +276,7 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
*/ */
public abstract int getPriority(); public abstract int getPriority();
public abstract void checkIfSuccessfulOrThrow() throws SmackException; public abstract void checkIfSuccessfulOrThrow() throws SmackSaslException;
public SASLMechanism instanceForAuthentication(XMPPConnection connection, ConnectionConfiguration connectionConfiguration) { public SASLMechanism instanceForAuthentication(XMPPConnection connection, ConnectionConfiguration connectionConfiguration) {
SASLMechanism saslMechansim = newInstance(); SASLMechanism saslMechansim = newInstance();

View File

@ -18,7 +18,6 @@ package org.jivesoftware.smack.sasl.core;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
/** /**
@ -41,13 +40,12 @@ public class SASLAnonymous extends SASLMechanism {
} }
@Override @Override
protected void authenticateInternal(CallbackHandler cbh) protected void authenticateInternal(CallbackHandler cbh) {
throws SmackException {
// Nothing to do here // Nothing to do here
} }
@Override @Override
protected byte[] getAuthenticationText() throws SmackException { protected byte[] getAuthenticationText() {
// ANONYMOUS has no initial response, return null // ANONYMOUS has no initial response, return null
return null; return null;
} }
@ -58,7 +56,7 @@ public class SASLAnonymous extends SASLMechanism {
} }
@Override @Override
public void checkIfSuccessfulOrThrow() throws SmackException { public void checkIfSuccessfulOrThrow() {
// SASL Anonymous is always successful :) // SASL Anonymous is always successful :)
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2014-2016 Florian Schmaus * Copyright 2014-2019 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,6 @@ package org.jivesoftware.smack.sasl.core;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
/** /**
@ -65,12 +64,12 @@ public class SASLXOauth2Mechanism extends SASLMechanism {
public static final String NAME = "X-OAUTH2"; public static final String NAME = "X-OAUTH2";
@Override @Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackException { protected void authenticateInternal(CallbackHandler cbh) {
throw new UnsupportedOperationException("CallbackHandler not (yet) supported"); throw new UnsupportedOperationException("CallbackHandler not (yet) supported");
} }
@Override @Override
protected byte[] getAuthenticationText() throws SmackException { protected byte[] getAuthenticationText() {
// Note that base64 encoding is done in SASLMechanism for the bytes return by getAuthenticationText(). // Note that base64 encoding is done in SASLMechanism for the bytes return by getAuthenticationText().
return toBytes('\u0000' + authenticationId + '\u0000' + password); return toBytes('\u0000' + authenticationId + '\u0000' + password);
} }
@ -92,7 +91,7 @@ public class SASLXOauth2Mechanism extends SASLMechanism {
} }
@Override @Override
public void checkIfSuccessfulOrThrow() throws SmackException { public void checkIfSuccessfulOrThrow() {
// No check performed // No check performed
} }
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2014-2017 Florian Schmaus * Copyright 2014-2019 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,6 +27,7 @@ import java.util.Random;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.ByteUtils; import org.jivesoftware.smack.util.ByteUtils;
import org.jivesoftware.smack.util.SHA1; import org.jivesoftware.smack.util.SHA1;
@ -79,12 +80,12 @@ public abstract class ScramMechanism extends SASLMechanism {
private byte[] serverSignature; private byte[] serverSignature;
@Override @Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackException { protected void authenticateInternal(CallbackHandler cbh) {
throw new UnsupportedOperationException("CallbackHandler not (yet) supported"); throw new UnsupportedOperationException("CallbackHandler not (yet) supported");
} }
@Override @Override
protected byte[] getAuthenticationText() throws SmackException { protected byte[] getAuthenticationText() {
clientRandomAscii = getRandomAscii(); clientRandomAscii = getRandomAscii();
String saslPrepedAuthcId = saslPrep(authenticationId); String saslPrepedAuthcId = saslPrep(authenticationId);
clientFirstMessageBare = "n=" + escape(saslPrepedAuthcId) + ",r=" + clientRandomAscii; clientFirstMessageBare = "n=" + escape(saslPrepedAuthcId) + ",r=" + clientRandomAscii;
@ -100,9 +101,9 @@ public abstract class ScramMechanism extends SASLMechanism {
} }
@Override @Override
public void checkIfSuccessfulOrThrow() throws SmackException { public void checkIfSuccessfulOrThrow() throws SmackSaslException {
if (state != State.VALID_SERVER_RESPONSE) { if (state != State.VALID_SERVER_RESPONSE) {
throw new SmackException("SCRAM-SHA1 is missing valid server response"); throw new SmackSaslException("SCRAM-SHA1 is missing valid server response");
} }
} }
@ -112,7 +113,7 @@ public abstract class ScramMechanism extends SASLMechanism {
} }
@Override @Override
protected byte[] evaluateChallenge(byte[] challenge) throws SmackException { protected byte[] evaluateChallenge(byte[] challenge) throws SmackSaslException {
String challengeString; String challengeString;
try { try {
// TODO: Where is it specified that this is an UTF-8 encoded string? // TODO: Where is it specified that this is an UTF-8 encoded string?
@ -130,33 +131,33 @@ public abstract class ScramMechanism extends SASLMechanism {
// Handle server random ASCII (nonce) // Handle server random ASCII (nonce)
String rvalue = attributes.get('r'); String rvalue = attributes.get('r');
if (rvalue == null) { if (rvalue == null) {
throw new SmackException("Server random ASCII is null"); throw new SmackSaslException("Server random ASCII is null");
} }
if (rvalue.length() <= clientRandomAscii.length()) { if (rvalue.length() <= clientRandomAscii.length()) {
throw new SmackException("Server random ASCII is shorter then client random ASCII"); throw new SmackSaslException("Server random ASCII is shorter then client random ASCII");
} }
String receivedClientRandomAscii = rvalue.substring(0, clientRandomAscii.length()); String receivedClientRandomAscii = rvalue.substring(0, clientRandomAscii.length());
if (!receivedClientRandomAscii.equals(clientRandomAscii)) { if (!receivedClientRandomAscii.equals(clientRandomAscii)) {
throw new SmackException("Received client random ASCII does not match client random ASCII"); throw new SmackSaslException("Received client random ASCII does not match client random ASCII");
} }
// Handle iterations // Handle iterations
int iterations; int iterations;
String iterationsString = attributes.get('i'); String iterationsString = attributes.get('i');
if (iterationsString == null) { if (iterationsString == null) {
throw new SmackException("Iterations attribute not set"); throw new SmackSaslException("Iterations attribute not set");
} }
try { try {
iterations = Integer.parseInt(iterationsString); iterations = Integer.parseInt(iterationsString);
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
throw new SmackException("Exception parsing iterations", e); throw new SmackSaslException("Exception parsing iterations", e);
} }
// Handle salt // Handle salt
String salt = attributes.get('s'); String salt = attributes.get('s');
if (salt == null) { if (salt == null) {
throw new SmackException("SALT not send"); throw new SmackSaslException("SALT not send");
} }
// Parsing and error checking is done, we can now begin to calculate the values // Parsing and error checking is done, we can now begin to calculate the values
@ -216,12 +217,12 @@ public abstract class ScramMechanism extends SASLMechanism {
case RESPONSE_SENT: case RESPONSE_SENT:
String clientCalculatedServerFinalMessage = "v=" + Base64.encodeToString(serverSignature); String clientCalculatedServerFinalMessage = "v=" + Base64.encodeToString(serverSignature);
if (!clientCalculatedServerFinalMessage.equals(challengeString)) { if (!clientCalculatedServerFinalMessage.equals(challengeString)) {
throw new SmackException("Server final message does not match calculated one"); throw new SmackSaslException("Server final message does not match calculated one");
} }
state = State.VALID_SERVER_RESPONSE; state = State.VALID_SERVER_RESPONSE;
break; break;
default: default:
throw new SmackException("Invalid state"); throw new SmackSaslException("Invalid state");
} }
return null; return null;
} }
@ -238,7 +239,7 @@ public abstract class ScramMechanism extends SASLMechanism {
return cbName + ',' + authzidPortion + ","; return cbName + ',' + authzidPortion + ",";
} }
private byte[] getCBindInput() throws SmackException { private byte[] getCBindInput() throws SmackSaslException {
byte[] cbindData = getChannelBindingData(); byte[] cbindData = getChannelBindingData();
byte[] gs2Header = toBytes(getGS2Header()); byte[] gs2Header = toBytes(getGS2Header());
@ -264,13 +265,13 @@ public abstract class ScramMechanism extends SASLMechanism {
/** /**
* *
* @return the Channel Binding data. * @return the Channel Binding data.
* @throws SmackException * @throws SmackSaslException
*/ */
protected byte[] getChannelBindingData() throws SmackException { protected byte[] getChannelBindingData() throws SmackSaslException {
return null; return null;
} }
private static Map<Character, String> parseAttributes(String string) throws SmackException { private static Map<Character, String> parseAttributes(String string) throws SmackSaslException {
if (string.length() == 0) { if (string.length() == 0) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
@ -279,11 +280,11 @@ public abstract class ScramMechanism extends SASLMechanism {
Map<Character, String> res = new HashMap<Character, String>(keyValuePairs.length, 1); Map<Character, String> res = new HashMap<Character, String>(keyValuePairs.length, 1);
for (String keyValuePair : keyValuePairs) { for (String keyValuePair : keyValuePairs) {
if (keyValuePair.length() < 3) { if (keyValuePair.length() < 3) {
throw new SmackException("Invalid Key-Value pair: " + keyValuePair); throw new SmackSaslException("Invalid Key-Value pair: " + keyValuePair);
} }
char key = keyValuePair.charAt(0); char key = keyValuePair.charAt(0);
if (keyValuePair.charAt(1) != '=') { if (keyValuePair.charAt(1) != '=') {
throw new SmackException("Invalid Key-Value pair: " + keyValuePair); throw new SmackSaslException("Invalid Key-Value pair: " + keyValuePair);
} }
String value = keyValuePair.substring(2); String value = keyValuePair.substring(2);
res.put(key, value); res.put(key, value);
@ -362,12 +363,12 @@ public abstract class ScramMechanism extends SASLMechanism {
* @return the HMAC-SHA1 value of the input. * @return the HMAC-SHA1 value of the input.
* @throws SmackException * @throws SmackException
*/ */
private byte[] hmac(byte[] key, byte[] str) throws SmackException { private byte[] hmac(byte[] key, byte[] str) throws SmackSaslException {
try { try {
return scramHmac.hmac(key, str); return scramHmac.hmac(key, str);
} }
catch (InvalidKeyException e) { catch (InvalidKeyException e) {
throw new SmackException(getName() + " Exception", e); throw new SmackSaslException(getName() + " Exception", e);
} }
} }
@ -382,9 +383,9 @@ public abstract class ScramMechanism extends SASLMechanism {
* @param salt * @param salt
* @param iterations * @param iterations
* @return the result of the Hi function. * @return the result of the Hi function.
* @throws SmackException * @throws SmackSaslException if a SASL related error occurs.
*/ */
private byte[] hi(String normalizedPassword, byte[] salt, int iterations) throws SmackException { private byte[] hi(String normalizedPassword, byte[] salt, int iterations) throws SmackSaslException {
byte[] key; byte[] key;
try { try {
// According to RFC 5802 § 2.2, the resulting string of the normalization is also in UTF-8. // According to RFC 5802 § 2.2, the resulting string of the normalization is also in UTF-8.

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2016 Florian Schmaus * Copyright 2016-2019 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@ import java.security.cert.CertificateEncodingException;
import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLPeerUnverifiedException;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.util.TLSUtils; import org.jivesoftware.smack.util.TLSUtils;
/** /**
@ -48,13 +48,13 @@ public abstract class ScramPlusMechanism extends ScramMechanism {
} }
@Override @Override
protected byte[] getChannelBindingData() throws SmackException { protected byte[] getChannelBindingData() throws SmackSaslException {
byte[] cbData; byte[] cbData;
try { try {
cbData = TLSUtils.getChannelBindingTlsServerEndPoint(sslSession); cbData = TLSUtils.getChannelBindingTlsServerEndPoint(sslSession);
} }
catch (SSLPeerUnverifiedException | CertificateEncodingException | NoSuchAlgorithmException e) { catch (SSLPeerUnverifiedException | CertificateEncodingException | NoSuchAlgorithmException e) {
throw new SmackException(e); throw new SmackSaslException(e);
} }
return cbData; return cbData;
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014 Florian Schmaus * Copyright © 2014-2019 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,7 +31,7 @@ import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient; import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException; import javax.security.sasl.SaslException;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
public abstract class SASLJavaXMechanism extends SASLMechanism { public abstract class SASLJavaXMechanism extends SASLMechanism {
@ -42,15 +42,15 @@ public abstract class SASLJavaXMechanism extends SASLMechanism {
public abstract String getName(); public abstract String getName();
@Override @Override
public final void checkIfSuccessfulOrThrow() throws SmackException { public final void checkIfSuccessfulOrThrow() throws SmackSaslException {
if (!sc.isComplete()) { if (!sc.isComplete()) {
throw new SmackException(getName() + " was not completed"); throw new SmackSaslException(getName() + " was not completed");
} }
} }
@Override @Override
protected void authenticateInternal() protected void authenticateInternal()
throws SmackException { throws SmackJavaxSaslException {
String[] mechanisms = { getName() }; String[] mechanisms = { getName() };
Map<String, String> props = getSaslProps(); Map<String, String> props = getSaslProps();
String authzid = null; String authzid = null;
@ -100,38 +100,38 @@ public abstract class SASLJavaXMechanism extends SASLMechanism {
}); });
} }
catch (SaslException e) { catch (SaslException e) {
throw new SmackException(e); throw new SmackJavaxSaslException(e);
} }
} }
@Override @Override
protected void authenticateInternal(CallbackHandler cbh) protected void authenticateInternal(CallbackHandler cbh)
throws SmackException { throws SmackJavaxSaslException {
String[] mechanisms = { getName() }; String[] mechanisms = { getName() };
Map<String, String> props = getSaslProps(); Map<String, String> props = getSaslProps();
try { try {
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, cbh); sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, cbh);
} }
catch (SaslException e) { catch (SaslException e) {
throw new SmackException(e); throw new SmackJavaxSaslException(e);
} }
} }
@Override @Override
protected byte[] getAuthenticationText() throws SmackException { protected byte[] getAuthenticationText() throws SmackJavaxSaslException {
if (sc.hasInitialResponse()) { if (sc.hasInitialResponse()) {
try { try {
return sc.evaluateChallenge(new byte[0]); return sc.evaluateChallenge(new byte[0]);
} }
catch (SaslException e) { catch (SaslException e) {
throw new SmackException(e); throw new SmackJavaxSaslException(e);
} }
} }
return null; return null;
} }
@Override @Override
protected byte[] evaluateChallenge(byte[] challenge) throws SmackException { protected byte[] evaluateChallenge(byte[] challenge) throws SmackJavaxSaslException {
try { try {
if (challenge != null) { if (challenge != null) {
return sc.evaluateChallenge(challenge); return sc.evaluateChallenge(challenge);
@ -141,7 +141,7 @@ public abstract class SASLJavaXMechanism extends SASLMechanism {
} }
} }
catch (SaslException e) { catch (SaslException e) {
throw new SmackException(e); throw new SmackJavaxSaslException(e);
} }
} }

View File

@ -0,0 +1,40 @@
/**
*
* Copyright 2019 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.sasl.javax;
import javax.security.sasl.SaslException;
import org.jivesoftware.smack.SmackException.SmackSaslException;
public class SmackJavaxSaslException extends SmackSaslException {
/**
*
*/
private static final long serialVersionUID = 1L;
private final SaslException saslException;
public SmackJavaxSaslException(SaslException saslException) {
super(saslException);
this.saslException = saslException;
}
public SaslException getSaslException() {
return saslException;
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2014-2017 Florian Schmaus * Copyright 2014-2019 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,7 @@ import java.io.UnsupportedEncodingException;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.ByteUtils; import org.jivesoftware.smack.util.ByteUtils;
import org.jivesoftware.smack.util.MD5; import org.jivesoftware.smack.util.MD5;
@ -60,12 +60,12 @@ public class SASLDigestMD5Mechanism extends SASLMechanism {
private String hex_hashed_a1; private String hex_hashed_a1;
@Override @Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackException { protected void authenticateInternal(CallbackHandler cbh) {
throw new UnsupportedOperationException("CallbackHandler not (yet) supported"); throw new UnsupportedOperationException("CallbackHandler not (yet) supported");
} }
@Override @Override
protected byte[] getAuthenticationText() throws SmackException { protected byte[] getAuthenticationText() {
// DIGEST-MD5 has no initial response, return null // DIGEST-MD5 has no initial response, return null
return null; return null;
} }
@ -92,16 +92,16 @@ public class SASLDigestMD5Mechanism extends SASLMechanism {
@Override @Override
public void checkIfSuccessfulOrThrow() throws SmackException { public void checkIfSuccessfulOrThrow() throws SmackSaslException {
if (verifyServerResponse && state != State.VALID_SERVER_RESPONSE) { if (verifyServerResponse && state != State.VALID_SERVER_RESPONSE) {
throw new SmackException(NAME + " no valid server response"); throw new SmackSaslException(NAME + " no valid server response");
} }
} }
@Override @Override
protected byte[] evaluateChallenge(byte[] challenge) throws SmackException { protected byte[] evaluateChallenge(byte[] challenge) throws SmackSaslException {
if (challenge.length == 0) { if (challenge.length == 0) {
throw new SmackException("Initial challenge has zero length"); throw new SmackSaslException("Initial challenge has zero length");
} }
String challengeString; String challengeString;
try { try {
@ -127,14 +127,14 @@ public class SASLDigestMD5Mechanism extends SASLMechanism {
String value = keyValue[1]; String value = keyValue[1];
if ("nonce".equals(key)) { if ("nonce".equals(key)) {
if (nonce != null) { if (nonce != null) {
throw new SmackException("Nonce value present multiple times"); throw new SmackSaslException("Nonce value present multiple times");
} }
nonce = value.replace("\"", ""); nonce = value.replace("\"", "");
} }
else if ("qop".equals(key)) { else if ("qop".equals(key)) {
value = value.replace("\"", ""); value = value.replace("\"", "");
if (!value.equals("auth")) { if (!value.equals("auth")) {
throw new SmackException("Unsupported qop operation: " + value); throw new SmackSaslException("Unsupported qop operation: " + value);
} }
} }
} }
@ -142,7 +142,7 @@ public class SASLDigestMD5Mechanism extends SASLMechanism {
// RFC 2831 2.1.1 about nonce "This directive is required and MUST appear exactly // RFC 2831 2.1.1 about nonce "This directive is required and MUST appear exactly
// once; if not present, or if multiple instances are present, the client should // once; if not present, or if multiple instances are present, the client should
// abort the authentication exchange." // abort the authentication exchange."
throw new SmackException("nonce value not present in initial challenge"); throw new SmackSaslException("nonce value not present in initial challenge");
} }
// RFC 2831 2.1.2.1 defines A1, A2, KD and response-value // RFC 2831 2.1.2.1 defines A1, A2, KD and response-value
byte[] a1FirstPart = MD5.bytes(authenticationId + ':' + serviceName + ':' byte[] a1FirstPart = MD5.bytes(authenticationId + ':' + serviceName + ':'
@ -188,12 +188,12 @@ public class SASLDigestMD5Mechanism extends SASLMechanism {
} }
} }
if (serverResponse == null) { if (serverResponse == null) {
throw new SmackException("No server response received while performing " + NAME throw new SmackSaslException("No server response received while performing " + NAME
+ " authentication"); + " authentication");
} }
String expectedServerResponse = calcResponse(DigestType.ServerResponse); String expectedServerResponse = calcResponse(DigestType.ServerResponse);
if (!serverResponse.equals(expectedServerResponse)) { if (!serverResponse.equals(expectedServerResponse)) {
throw new SmackException("Invalid server response while performing " + NAME throw new SmackSaslException("Invalid server response while performing " + NAME
+ " authentication"); + " authentication");
} }
} }

View File

@ -18,7 +18,6 @@ package org.jivesoftware.smack.sasl.provided;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
@ -34,13 +33,13 @@ public class SASLExternalMechanism extends SASLMechanism {
public static final String NAME = EXTERNAL; public static final String NAME = EXTERNAL;
@Override @Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackException { protected void authenticateInternal(CallbackHandler cbh) {
// Do nothing. Auth will be done external to Smack and which will receive the localpart // Do nothing. Auth will be done external to Smack and which will receive the localpart
// after the resource binding // after the resource binding
} }
@Override @Override
protected byte[] getAuthenticationText() throws SmackException { protected byte[] getAuthenticationText() {
if (authorizationId != null) { if (authorizationId != null) {
return toBytes(authorizationId.toString()); return toBytes(authorizationId.toString());
} }
@ -68,7 +67,7 @@ public class SASLExternalMechanism extends SASLMechanism {
} }
@Override @Override
public void checkIfSuccessfulOrThrow() throws SmackException { public void checkIfSuccessfulOrThrow() {
// No check performed // No check performed
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2014 Florian Schmaus * Copyright 2014-2019 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,6 @@ package org.jivesoftware.smack.sasl.provided;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.ByteUtils; import org.jivesoftware.smack.util.ByteUtils;
@ -27,12 +26,12 @@ public class SASLPlainMechanism extends SASLMechanism {
public static final String NAME = PLAIN; public static final String NAME = PLAIN;
@Override @Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackException { protected void authenticateInternal(CallbackHandler cbh) {
throw new UnsupportedOperationException("CallbackHandler not (yet) supported"); throw new UnsupportedOperationException("CallbackHandler not (yet) supported");
} }
@Override @Override
protected byte[] getAuthenticationText() throws SmackException { protected byte[] getAuthenticationText() {
// concatenate and encode username (authcid) and password // concatenate and encode username (authcid) and password
String authzid; String authzid;
if (authorizationId == null) { if (authorizationId == null) {
@ -62,7 +61,7 @@ public class SASLPlainMechanism extends SASLMechanism {
} }
@Override @Override
public void checkIfSuccessfulOrThrow() throws SmackException { public void checkIfSuccessfulOrThrow() {
// No check performed // No check performed
} }