Commit bcd82dc3 authored by Jay Kline's avatar Jay Kline Committed by jay

Enables EXTERNAL auth for c2s connections (SSL client certificates)


git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@9111 b35dd754-fafc-0310-a699-88a17e54d16e
parent 19a5b349
...@@ -22,8 +22,7 @@ import org.xmpp.packet.IQ; ...@@ -22,8 +22,7 @@ import org.xmpp.packet.IQ;
import org.xmpp.packet.Message; import org.xmpp.packet.Message;
import org.xmpp.packet.Presence; import org.xmpp.packet.Presence;
/** /** Handler of XML stanzas sent by clients connected directly to the server. Received packet will
* Handler of XML stanzas sent by clients connected directly to the server. Received packet will
* have their FROM attribute overriden to avoid spoofing.<p> * have their FROM attribute overriden to avoid spoofing.<p>
* *
* By default the hostname specified in the stream header sent by clients will not be validated. * By default the hostname specified in the stream header sent by clients will not be validated.
...@@ -92,6 +91,15 @@ public class ClientStanzaHandler extends StanzaHandler { ...@@ -92,6 +91,15 @@ public class ClientStanzaHandler extends StanzaHandler {
} }
void startTLS() throws Exception { void startTLS() throws Exception {
connection.startTLS(false, null, Connection.ClientAuth.disabled);
Connection.ClientAuth policy;
try {
policy =
Connection.ClientAuth.valueOf(JiveGlobals.getProperty("xmpp.client.cert.policy",
"required"));
} catch (IllegalArgumentException e) {
policy = Connection.ClientAuth.disabled;
}
connection.startTLS(false, null, policy);
} }
} }
...@@ -19,8 +19,8 @@ import org.jivesoftware.openfire.XMPPServer; ...@@ -19,8 +19,8 @@ import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.AuthorizationManager; import org.jivesoftware.openfire.auth.AuthorizationManager;
import org.jivesoftware.openfire.auth.AuthFactory; import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.auth.AuthToken; import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.session.*; import org.jivesoftware.openfire.session.*;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.util.CertificateManager; import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
...@@ -117,6 +117,8 @@ public class SASLAuthentication { ...@@ -117,6 +117,8 @@ public class SASLAuthentication {
* the session's connection is not secured then only include the SASL mechanisms that don't * the session's connection is not secured then only include the SASL mechanisms that don't
* require TLS. * require TLS.
* *
* @param session The current session
*
* @return a string with the valid SASL mechanisms available for the specified session. * @return a string with the valid SASL mechanisms available for the specified session.
*/ */
public static String getSASLMechanisms(Session session) { public static String getSASLMechanisms(Session session) {
...@@ -441,14 +443,20 @@ public class SASLAuthentication { ...@@ -441,14 +443,20 @@ public class SASLAuthentication {
Log.warn("Error retrieving client certificates of: " + session, e); Log.warn("Error retrieving client certificates of: " + session, e);
} }
} }
else { else if (session instanceof LocalClientSession) {
// Client EXTERNALL login // Client EXTERNALL login
Log.debug("SASLAuthentication: EXTERNAL authentication via SSL certs for c2s connection"); Log.debug("SASLAuthentication: EXTERNAL authentication via SSL certs for c2s connection");
// This may be null, we will deal with that later // This may be null, we will deal with that later
String username = doc.getTextTrim(); String username = new String(StringUtils.decodeBase64(doc.getTextTrim()), CHARSET);
String principal = ""; String principal = "";
ArrayList<String> principals = new ArrayList<String>(); ArrayList<String> principals = new ArrayList<String>();
SocketConnection connection = (SocketConnection)session.getConnection(); Connection connection = session.getConnection();
if (connection.getSSLSession() == null) {
Log.debug("SASLAuthentication: EXTERNAL authentication requested, but no SSL/TLS connection found.");
authenticationFailed(session);
return Status.failed;
}
try { try {
for (Certificate certificate : connection.getSSLSession().getPeerCertificates()) { for (Certificate certificate : connection.getSSLSession().getPeerCertificates()) {
principals.addAll(CertificateManager.getPeerIdentities((X509Certificate)certificate)); principals.addAll(CertificateManager.getPeerIdentities((X509Certificate)certificate));
...@@ -458,6 +466,9 @@ public class SASLAuthentication { ...@@ -458,6 +466,9 @@ public class SASLAuthentication {
Log.warn("Error retrieving client certificates of: " + session, e); Log.warn("Error retrieving client certificates of: " + session, e);
} }
principal = principals.get(0);
if (username == null || username.length() == 0) { if (username == null || username.length() == 0) {
// No username was provided, according to XEP-0178 we need to: // No username was provided, according to XEP-0178 we need to:
// * attempt to get it from the cert first // * attempt to get it from the cert first
...@@ -467,8 +478,6 @@ public class SASLAuthentication { ...@@ -467,8 +478,6 @@ public class SASLAuthentication {
// We set principal to the first one in the list to have a sane default // We set principal to the first one in the list to have a sane default
// If this list is empty, then the cert had no identity at all, which // If this list is empty, then the cert had no identity at all, which
// will cause an authorization failure // will cause an authorization failure
principal = principals.get(0);
for(String princ : principals) { for(String princ : principals) {
String u = AuthorizationManager.map(princ); String u = AuthorizationManager.map(princ);
if(!u.equals(princ)) { if(!u.equals(princ)) {
...@@ -477,14 +486,21 @@ public class SASLAuthentication { ...@@ -477,14 +486,21 @@ public class SASLAuthentication {
break; break;
} }
} }
if (username == null || username.length() == 0) {
// Still no username. Punt.
username = principal;
}
Log.debug("SASLAuthentication: no username requested, using "+username); Log.debug("SASLAuthentication: no username requested, using "+username);
} }
//Its possible that either/both username and principal are null here //Its possible that either/both username and principal are null here
//The providers should not allow a null authorization //The providers should not allow a null authorization
if (AuthorizationManager.authorize(username,principal)) { if (AuthorizationManager.authorize(username,principal)) {
Log.debug("SASLAuthentication: "+principal+" authorized to "+username); Log.debug("SASLAuthentication: "+principal+" authorized to "+username);
return Status.authenticated; return Status.authenticated;
} }
} else {
Log.debug("SASLAuthentication: unknown session type. Cannot perform EXTERNAL authentication");
} }
authenticationFailed(session); authenticationFailed(session);
return Status.failed; return Status.failed;
......
...@@ -402,7 +402,14 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana ...@@ -402,7 +402,14 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
trustFactory.getTrustManagers(), trustFactory.getTrustManagers(),
new java.security.SecureRandom()); new java.security.SecureRandom());
sslSocketAcceptor.getFilterChain().addFirst("tls", new SSLFilter(sslContext)); SSLFilter sslFilter = new SSLFilter(sslContext);
if (JiveGlobals.getProperty("xmpp.client.cert.policy","disabled").equals("needed")) {
sslFilter.setNeedClientAuth(true);
}
else if(JiveGlobals.getProperty("xmpp.client.cert.policy","disabled").equals("wanted")) {
sslFilter.setWantClientAuth(true);
}
sslSocketAcceptor.getFilterChain().addFirst("tls", sslFilter);
} }
catch (Exception e) { catch (Exception e) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment