mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-12-23 21:17:58 +01:00
1. Allow to perform SASL authentication over plain connections. SMACK-83
2. Added support for ANONYMOUS SASL authentication. SMACK-84 3. Fixed isSecureConnection to return true when using TLS. git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2785 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
391e7269e6
commit
2303fa33c9
1 changed files with 48 additions and 59 deletions
|
@ -22,23 +22,25 @@ package org.jivesoftware.smack;
|
||||||
|
|
||||||
import org.jivesoftware.smack.debugger.SmackDebugger;
|
import org.jivesoftware.smack.debugger.SmackDebugger;
|
||||||
import org.jivesoftware.smack.filter.PacketFilter;
|
import org.jivesoftware.smack.filter.PacketFilter;
|
||||||
import org.jivesoftware.smack.filter.PacketIDFilter;
|
|
||||||
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||||
import org.jivesoftware.smack.packet.*;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
|
import org.jivesoftware.smack.packet.XMPPError;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a connection to a XMPP server. A simple use of this API might
|
* Creates a connection to a XMPP server. A simple use of this API might
|
||||||
|
@ -334,7 +336,9 @@ public class XMPPConnection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs in to the server using the strongest authentication mode supported by
|
* Logs in to the server using the strongest authentication mode supported by
|
||||||
* the server. An available presence may optionally be sent. If <tt>sendPresence</tt>
|
* the server. If the server supports SASL authentication then the user will be
|
||||||
|
* authenticated using SASL if not Non-SASL authentication will be tried. An available
|
||||||
|
* presence may optionally be sent. If <tt>sendPresence</tt>
|
||||||
* is false, a presence packet must be sent manually later. If more than five seconds
|
* is false, a presence packet must be sent manually later. If more than five seconds
|
||||||
* (default timeout) elapses in each step of the authentication process without a
|
* (default timeout) elapses in each step of the authentication process without a
|
||||||
* response from the server, or if an error occurs, a XMPPException will be thrown.
|
* response from the server, or if an error occurs, a XMPPException will be thrown.
|
||||||
|
@ -361,7 +365,7 @@ public class XMPPConnection {
|
||||||
username = username.toLowerCase().trim();
|
username = username.toLowerCase().trim();
|
||||||
|
|
||||||
String response = null;
|
String response = null;
|
||||||
if (usingTLS) {
|
if (saslAuthentication.hasNonAnonymousAuthentication()) {
|
||||||
// Authenticate using SASL
|
// Authenticate using SASL
|
||||||
response = saslAuthentication.authenticate(username, password, resource);
|
response = saslAuthentication.authenticate(username, password, resource);
|
||||||
}
|
}
|
||||||
|
@ -398,7 +402,7 @@ public class XMPPConnection {
|
||||||
|
|
||||||
// If debugging is enabled, change the the debug window title to include the
|
// If debugging is enabled, change the the debug window title to include the
|
||||||
// name we are now logged-in as.
|
// name we are now logged-in as.
|
||||||
// If DEBUG_ENABLED was set to true AFTER the connection was created the debugger
|
// If DEBUG_ENABLED was set to true AFTER the connection was created the debugger
|
||||||
// will be null
|
// will be null
|
||||||
if (DEBUG_ENABLED && debugger != null) {
|
if (DEBUG_ENABLED && debugger != null) {
|
||||||
debugger.userHasLogged(user);
|
debugger.userHasLogged(user);
|
||||||
|
@ -423,30 +427,19 @@ public class XMPPConnection {
|
||||||
throw new IllegalStateException("Already logged in to server.");
|
throw new IllegalStateException("Already logged in to server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the authentication packet we'll send to the server.
|
String response = null;
|
||||||
Authentication auth = new Authentication();
|
if (saslAuthentication.hasAnonymousAuthentication()) {
|
||||||
|
response = saslAuthentication.authenticateAnonymously();
|
||||||
PacketCollector collector =
|
|
||||||
packetReader.createPacketCollector(new PacketIDFilter(auth.getPacketID()));
|
|
||||||
// Send the packet.
|
|
||||||
packetWriter.sendPacket(auth);
|
|
||||||
// Wait up to a certain number of seconds for a response from the server.
|
|
||||||
IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
|
||||||
if (response == null) {
|
|
||||||
throw new XMPPException("Anonymous login failed.");
|
|
||||||
}
|
|
||||||
else if (response.getType() == IQ.Type.ERROR) {
|
|
||||||
throw new XMPPException(response.getError());
|
|
||||||
}
|
|
||||||
// Set the user value.
|
|
||||||
if (response.getTo() != null) {
|
|
||||||
this.user = response.getTo();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.user = this.serviceName + "/" + ((Authentication) response).getResource();
|
// Authenticate using Non-SASL
|
||||||
|
response = new NonSASLAuthentication(this).authenticateAnonymously();
|
||||||
}
|
}
|
||||||
// We're done with the collector, so explicitly cancel it.
|
|
||||||
collector.cancel();
|
// Set the user value.
|
||||||
|
this.user = response;
|
||||||
|
// Update the serviceName with the one returned by the server
|
||||||
|
this.serviceName = StringUtils.parseServer(response);
|
||||||
|
|
||||||
// Anonymous users can't have a roster.
|
// Anonymous users can't have a roster.
|
||||||
roster = null;
|
roster = null;
|
||||||
|
@ -460,7 +453,7 @@ public class XMPPConnection {
|
||||||
|
|
||||||
// If debugging is enabled, change the the debug window title to include the
|
// If debugging is enabled, change the the debug window title to include the
|
||||||
// name we are now logged-in as.
|
// name we are now logged-in as.
|
||||||
// If DEBUG_ENABLED was set to true AFTER the connection was created the debugger
|
// If DEBUG_ENABLED was set to true AFTER the connection was created the debugger
|
||||||
// will be null
|
// will be null
|
||||||
if (DEBUG_ENABLED && debugger != null) {
|
if (DEBUG_ENABLED && debugger != null) {
|
||||||
debugger.userHasLogged(user);
|
debugger.userHasLogged(user);
|
||||||
|
@ -563,12 +556,13 @@ public class XMPPConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the connection is a secured one, such as an SSL connection.
|
* Returns true if the connection is a secured one, such as an SSL connection or
|
||||||
|
* if TLS was negotiated successfully.
|
||||||
*
|
*
|
||||||
* @return true if a secure connection to the server.
|
* @return true if a secure connection to the server.
|
||||||
*/
|
*/
|
||||||
public boolean isSecureConnection() {
|
public boolean isSecureConnection() {
|
||||||
return false;
|
return isUsingTLS();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -730,7 +724,7 @@ public class XMPPConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a connection established listener that will be notified when a new connection
|
* Adds a connection established listener that will be notified when a new connection
|
||||||
* is established.
|
* is established.
|
||||||
*
|
*
|
||||||
* @param connectionEstablishedListener a listener interested on connection established events.
|
* @param connectionEstablishedListener a listener interested on connection established events.
|
||||||
|
@ -975,35 +969,30 @@ public class XMPPConnection {
|
||||||
* existing plain connection and perform a handshake. This method won't return until the
|
* existing plain connection and perform a handshake. This method won't return until the
|
||||||
* connection has finished the handshake or an error occured while securing the connection.
|
* connection has finished the handshake or an error occured while securing the connection.
|
||||||
*/
|
*/
|
||||||
void proceedTLSReceived() {
|
void proceedTLSReceived() throws Exception {
|
||||||
try {
|
SSLContext context = SSLContext.getInstance("TLS");
|
||||||
SSLContext context = SSLContext.getInstance("TLS");
|
// Accept any certificate presented by the server
|
||||||
// Accept any certificate presented by the server
|
context.init(null, // KeyManager not required
|
||||||
context.init(null, // KeyManager not required
|
new javax.net.ssl.TrustManager[]{new OpenTrustManager()},
|
||||||
new javax.net.ssl.TrustManager[] { new OpenTrustManager() },
|
new java.security.SecureRandom());
|
||||||
new java.security.SecureRandom());
|
Socket plain = socket;
|
||||||
Socket plain = socket;
|
// Secure the plain connection
|
||||||
// Secure the plain connection
|
socket = context.getSocketFactory().createSocket(plain,
|
||||||
socket = context.getSocketFactory().createSocket(plain,
|
plain.getInetAddress().getHostName(), plain.getPort(), true);
|
||||||
plain.getInetAddress().getHostName(), plain.getPort(), true);
|
socket.setSoTimeout(0);
|
||||||
socket.setSoTimeout(0);
|
socket.setKeepAlive(true);
|
||||||
socket.setKeepAlive(true);
|
// Initialize the reader and writer with the new secured version
|
||||||
// Initialize the reader and writer with the new secured version
|
initReaderAndWriter();
|
||||||
initReaderAndWriter();
|
// Proceed to do the handshake
|
||||||
// Proceed to do the handshake
|
((SSLSocket) socket).startHandshake();
|
||||||
((SSLSocket)socket).startHandshake();
|
|
||||||
|
|
||||||
// Set that TLS was successful
|
// Set that TLS was successful
|
||||||
usingTLS = true;
|
usingTLS = true;
|
||||||
|
|
||||||
// Set the new writer to use
|
// Set the new writer to use
|
||||||
packetWriter.setWriter(writer);
|
packetWriter.setWriter(writer);
|
||||||
// Send a new opening stream to the server
|
// Send a new opening stream to the server
|
||||||
packetWriter.openStream();
|
packetWriter.openStream();
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
packetReader.notifyConnectionError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue