You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by cr...@apache.org on 2001/07/30 22:04:05 UTC
cvs commit: jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm RealmBase.java
craigmcc 01/07/30 13:04:05
Modified: catalina/src/share/org/apache/catalina Realm.java
catalina/src/share/org/apache/catalina/authenticator
LocalStrings.properties SSLAuthenticator.java
catalina/src/share/org/apache/catalina/realm RealmBase.java
Log:
Realm: Add a new authenticate() method signature that takes a client
certificate chain (presumably provided when the CLIENT-CERT login method
is selected.
RealmBase: Provide a default implementation of the new authenticate()
signature that does the following:
* (Optionally, but default=true) Ask the certificate chain to check
validity on each included certificate.
* Call the getPrincipal() method of the actual implementation class
to return a Principal based on the username of the first certificate
in the chain (i.e. the client itself). As a side effect of this change,
role lookups for CLIENT-CERT authenticated principals will now work
the same as for BASIC, DIGEST, and FORM based authentications.
SSLAuthenticator: Use the new Realm.authenticate() signature in a manner
similar to that used by the other Authenticator implementations.
This is a partial solution to BugTraq #4485977.
Revision Changes Path
1.4 +15 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Realm.java
Index: Realm.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Realm.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Realm.java 2001/07/22 20:13:30 1.3
+++ Realm.java 2001/07/30 20:04:04 1.4
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Realm.java,v 1.3 2001/07/22 20:13:30 pier Exp $
- * $Revision: 1.3 $
- * $Date: 2001/07/22 20:13:30 $
+ * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Realm.java,v 1.4 2001/07/30 20:04:04 craigmcc Exp $
+ * $Revision: 1.4 $
+ * $Date: 2001/07/30 20:04:04 $
*
* ====================================================================
*
@@ -67,6 +67,7 @@
import java.beans.PropertyChangeListener;
import java.security.Principal;
+import java.security.cert.X509Certificate;
/**
@@ -77,7 +78,7 @@
* Container.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.3 $ $Date: 2001/07/22 20:13:30 $
+ * @version $Revision: 1.4 $ $Date: 2001/07/30 20:04:04 $
*/
public interface Realm {
@@ -158,6 +159,16 @@
String nonce, String nc, String cnonce,
String qop, String realm,
String md5a2);
+
+
+ /**
+ * Return the Principal associated with the specified chain of X509
+ * client certificates. If there is none, return <code>null</code>.
+ *
+ * @param certs Array of client certificates, with the first one in
+ * the array being the certificate of the client itself.
+ */
+ public Principal authenticate(X509Certificate certs[]);
/**
1.3 +1 -0 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/LocalStrings.properties
Index: LocalStrings.properties
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/LocalStrings.properties,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- LocalStrings.properties 2000/09/12 00:10:09 1.2
+++ LocalStrings.properties 2001/07/30 20:04:04 1.3
@@ -7,4 +7,5 @@
authenticator.notAuthenticated=Configuration error: Cannot perform access control without an authenticated principal
authenticator.notContext=Configuration error: Must be attached to a Context
authenticator.notStarted=Security Interceptor has not yet been started
+authenticator.unauthorized=Cannot authenticate with the provided credentials
authenticator.userDataConstraint=This request violates a User Data constraint for this application
1.8 +19 -23 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java
Index: SSLAuthenticator.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- SSLAuthenticator.java 2001/07/22 20:09:19 1.7
+++ SSLAuthenticator.java 2001/07/30 20:04:04 1.8
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v 1.7 2001/07/22 20:09:19 pier Exp $
- * $Revision: 1.7 $
- * $Date: 2001/07/22 20:09:19 $
+ * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v 1.8 2001/07/30 20:04:04 craigmcc Exp $
+ * $Revision: 1.8 $
+ * $Date: 2001/07/30 20:04:04 $
*
* ====================================================================
*
@@ -86,7 +86,7 @@
* that utilizes SSL certificates to identify client users.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.7 $ $Date: 2001/07/22 20:09:19 $
+ * @version $Revision: 1.8 $ $Date: 2001/07/30 20:04:04 $
*/
public final class SSLAuthenticator
@@ -137,10 +137,15 @@
// Have we already authenticated someone?
Principal principal =
((HttpServletRequest) request.getRequest()).getUserPrincipal();
- if (principal != null)
+ if (principal != null) {
+ if (debug >= 1)
+ log("Already authenticated '" + principal.getName() + "'");
return (true);
+ }
// Retrieve the certificate chain for this client
+ HttpServletResponse hres =
+ (HttpServletResponse) response.getResponse();
if (debug >= 1)
log(" Looking up certificates");
X509Certificate certs[] = (X509Certificate[])
@@ -148,28 +153,19 @@
if ((certs == null) || (certs.length < 1)) {
if (debug >= 1)
log(" No certificates included with this request");
- ((HttpServletResponse) response.getResponse()).
- sendError(HttpServletResponse.SC_BAD_REQUEST,
- sm.getString("authenticator.certificates"));
+ hres.sendError(HttpServletResponse.SC_BAD_REQUEST,
+ sm.getString("authenticator.certificates"));
return (false);
}
- principal = certs[0].getSubjectDN();
- // Check the validity of each certificate in the chain
- for (int i = 0; i < certs.length; i++) {
+ // Authenticate the specified certificate chain
+ principal = context.getRealm().authenticate(certs);
+ if (principal == null) {
if (debug >= 1)
- log(" Checking validity for '" +
- certs[i].getSubjectDN().getName() + "'");
- try {
- certs[i].checkValidity();
- } catch (Exception e) {
- if (debug >= 1)
- log(" Validity exception", e);
- ((HttpServletResponse) response.getResponse()).
- sendError(HttpServletResponse.SC_FORBIDDEN,
- sm.getString("authenticator.invalid"));
- return (false);
- }
+ log(" Realm.authenticate() returned false");
+ hres.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+ sm.getString("authenticator.unauthorized"));
+ return (false);
}
// Cache the principal (if requested) and record this authentication
1.5 +69 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java
Index: RealmBase.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- RealmBase.java 2001/07/22 20:25:11 1.4
+++ RealmBase.java 2001/07/30 20:04:04 1.5
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v 1.4 2001/07/22 20:25:11 pier Exp $
- * $Revision: 1.4 $
- * $Date: 2001/07/22 20:25:11 $
+ * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v 1.5 2001/07/30 20:04:04 craigmcc Exp $
+ * $Revision: 1.5 $
+ * $Date: 2001/07/30 20:04:04 $
*
* ====================================================================
*
@@ -70,6 +70,7 @@
import java.security.Principal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
import java.io.File;
import org.apache.catalina.Container;
import org.apache.catalina.Lifecycle;
@@ -94,7 +95,7 @@
* location) are identical to those currently supported by Tomcat 3.X.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.4 $ $Date: 2001/07/22 20:25:11 $
+ * @version $Revision: 1.5 $ $Date: 2001/07/30 20:04:04 $
*/
public abstract class RealmBase
@@ -175,6 +176,12 @@
protected PropertyChangeSupport support = new PropertyChangeSupport(this);
+ /**
+ * Should we validate client certificate chains when they are presented?
+ */
+ protected boolean validate = true;
+
+
// ------------------------------------------------------------- Properties
@@ -257,6 +264,28 @@
}
+ /**
+ * Return the "validate certificate chains" flag.
+ */
+ public boolean getValidate() {
+
+ return (this.validate);
+
+ }
+
+
+ /**
+ * Set the "validate certificate chains" flag.
+ *
+ * @param validate The new validate certificate chains flag
+ */
+ public void setValidate(boolean validate) {
+
+ this.validate = validate;
+
+ }
+
+
// --------------------------------------------------------- Public Methods
@@ -356,6 +385,42 @@
return null;
}
+
+
+ /**
+ * Return the Principal associated with the specified chain of X509
+ * client certificates. If there is none, return <code>null</code>.
+ *
+ * @param certs Array of client certificates, with the first one in
+ * the array being the certificate of the client itself.
+ */
+ public Principal authenticate(X509Certificate certs[]) {
+
+ if ((certs == null) || (certs.length < 1))
+ return (null);
+
+ // Check the validity of each certificate in the chain
+ if (debug >= 1)
+ log("Authenticating client certificate chain");
+ if (validate) {
+ for (int i = 0; i < certs.length; i++) {
+ if (debug >= 2)
+ log(" Checking validity for '" +
+ certs[i].getSubjectDN().getName() + "'");
+ try {
+ certs[i].checkValidity();
+ } catch (Exception e) {
+ if (debug >= 2)
+ log(" Validity exception", e);
+ return (null);
+ }
+ }
+ }
+
+ // Check the existence of the client Principal in our database
+ return (getPrincipal(certs[0].getSubjectDN().getName()));
+
+ }
/**