ASF Bugzilla – Attachment 28386 Details for
Bug 52500
Improve client certificate authentication
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
x509 java code
x509.patch (text/plain), 15.89 KB, created by
Michael
on 2012-02-26 20:38:32 UTC
(
hide
)
Description:
x509 java code
Filename:
MIME Type:
Creator:
Michael
Created:
2012-02-26 20:38:32 UTC
Size:
15.89 KB
patch
obsolete
>Index: org/apache/catalina/realm/X509SubjectDnRetriever.java >=================================================================== >--- org/apache/catalina/realm/X509SubjectDnRetriever.java (revision 0) >+++ org/apache/catalina/realm/X509SubjectDnRetriever.java (revision 0) >@@ -0,0 +1,204 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You 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.apache.catalina.realm; >+ >+import java.security.cert.X509Certificate; >+import java.util.Arrays; >+import java.util.List; >+ >+import javax.naming.InvalidNameException; >+import javax.naming.ldap.LdapName; >+import javax.naming.ldap.Rdn; >+ >+import org.apache.juli.logging.Log; >+import org.apache.juli.logging.LogFactory; >+ >+ >+/** >+ * Implementation of <b>X509UserNameRetriever</b> that takes a user name from the Subject Field of the X509Certificate. >+ * The user name is the unique part of information from the client certificate that used to identify the identity of the user. >+ * The Subject field (also called Subject Distinguish Name or SubjectDN) identifies the entity associated with the public key. >+ * The Subject field contains the following relevant attributes (it can also contain other attributes). >+ * >+ * Subject Attribute Subject Attribute Description Example >+ * CN Common Name CN=Bob BobFamily >+ * emailAddress Email Address emailAddress=bob@example.com >+ * C Country Name C=US >+ * ST State or Province Name ST=NY >+ * L Locality Name L=New York >+ * O Organization Name O=Work Organization >+ * OU Organizational Unit Name OU=Managers >+ * >+ * To retrieve the user name from the subject, you can use the entire SubjectDN field or the SubjectDN attribute. >+ * To retrieve the user name from entire SubjectDN field use the default constructor >+ * To retrieve the user name from the SubjectDN attribute, please provide the retrieve attribute name >+ * The the retrieve attribute name is a code letter based on a legend defined in the certificate itself. >+ * >+ * For example, the Email attribute is used to hold the User Name. >+ * Please provide "e" or "emailAddress" for the constructor. >+ * >+ * For example, the Common Name attribute is used to hold the User Name. >+ * Please provide "CN" for the constructor. >+ * >+ * >+ */ >+public class X509SubjectDnRetriever implements X509UserNameRetriever { >+ /** >+ * Logger for this class >+ */ >+ protected final Log log = LogFactory.getLog(getClass()); >+ >+ private static final String EMAIL_SUBJECT_ATTR = "emailAddress"; >+ >+ >+ /** >+ * The value is based on a legend defined in the certificate itself. >+ * It tested with the following browsers: IE, FF and Chrome >+ * For new browsers may be will required to add a new legend value to the list. >+ */ >+ private static final List<String> EmailOptions = Arrays.asList(EMAIL_SUBJECT_ATTR.toLowerCase(), "e") ; >+ >+ >+ private String subjectDnAttribute = null; >+ private String subjectDnAttributeConfiguration = null; >+ >+ protected X509SubjectDnRetriever() { >+ setSubjectDnAttribute(null); >+ } >+ >+ protected X509SubjectDnRetriever(String retrieveAttr) { >+ setSubjectDnAttribute(retrieveAttr); >+ } >+ >+ /** >+ * Set the configuration for X509UserNameRetriever. The X509UserNameRetriever uses the configuration >+ * to retrieve a user name from X509Certificate. >+ * >+ * @param x509UserNameRetrieverConfiguration >+ */ >+ public void setX509UserNameRetrieverConfiguration(String x509UserNameRetrieverConfiguration) { >+ setSubjectDnAttribute(x509UserNameRetrieverConfiguration); >+ >+ } >+ /* (non-Javadoc) >+ * @see org.apache.catalina.realm.X509UserNameRetriever#getUserName(java.security.cert.X509Certificate) >+ */ >+ public String getUserName(X509Certificate clientCert) { >+ if (log.isDebugEnabled()) { >+ log.debug("getUserName(X509Certificate) - start"); >+ } >+ String subject = getSubjectDN(clientCert); >+ String userName = null; >+ >+ if (subject != null) { >+ if (log.isDebugEnabled()) { >+ log.debug("Subject is [" + subject + "]."); >+ } >+ if (subjectDnAttribute == null) { >+ if (log.isDebugEnabled()) { >+ log.debug("subjectDnAttribute is null, so return the whole subject."); >+ } >+ userName = subject; >+ } else { >+ boolean foundUserName = false; >+ try { >+ LdapName ldapName = new LdapName(subject); >+ List<Rdn> list = ldapName.getRdns(); >+ if (list != null) { >+ for (Rdn rdn : list) { >+ String type = rdn.getType(); >+ if (subjectDnAttribute.equalsIgnoreCase(type.toString())) { >+ Object value = rdn.getValue(); >+ if (value instanceof String) { >+ userName = (String) value; >+ foundUserName = true; >+ if (log.isDebugEnabled()) { >+ log.debug("Success to retreive userName [" + userName + "]."); >+ } >+ break; >+ } >+ } >+ } >+ } >+ } catch (InvalidNameException e) { >+ log.info("subject [" + subject + "] is not valid name : [" + e.getMessage() + "]."); >+ } >+ if (!foundUserName) { >+ log.info("subject [" + subject + "] does not contain the required attribute [" + subjectDnAttributeConfiguration + "]. Return the whole subject."); >+ userName = subject; >+ } >+ } >+ >+ } >+ >+ if (log.isDebugEnabled()) { >+ log.debug("getUserName(X509Certificate) - end; Ret is [" + userName + "]."); >+ } >+ return userName; >+ } >+ >+ private void setSubjectDnAttribute(String subjectDnAttributeConfiguration) { >+ this.subjectDnAttributeConfiguration = subjectDnAttributeConfiguration; >+ subjectDnAttribute = mapSubjectDnAttribute(subjectDnAttributeConfiguration); >+ if (log.isDebugEnabled()) { >+ log.debug("setSubjectDnAttribute(String) - end; subjectDnAttribute [" + subjectDnAttribute + "]; subjectDnAttributeConfiguration [" + subjectDnAttributeConfiguration + "]"); >+ } >+ } >+ >+ >+ >+ private String mapSubjectDnAttribute(String subjectDnAttributeConfiguration) { >+ String ret = null; >+ if (subjectDnAttributeConfiguration != null) { >+ if (EmailOptions.contains(subjectDnAttributeConfiguration.toLowerCase())) { >+ ret = EMAIL_SUBJECT_ATTR; >+ } else { >+ ret = subjectDnAttributeConfiguration; >+ } >+ } >+ return ret; >+ } >+ >+ /** >+ * @param clientCert >+ * @return the whole SubjectSN of the X509Certificate >+ */ >+ protected String getSubjectDN(X509Certificate clientCert) { >+ String subject = null; >+ if (clientCert != null) { >+ if ((clientCert.getSubjectDN()!= null) >+ && (clientCert.getSubjectDN().getName() != null)) { >+ subject = clientCert.getSubjectDN().getName(); >+ } else { >+ if (log.isDebugEnabled()) { >+ log.debug("Can not getSubjectDN, SubjectDN is null"); >+ } >+ } >+ } else { >+ if (log.isDebugEnabled()) { >+ log.debug("Can not getSubjectDN, clientCert is null"); >+ } >+ } >+ if (log.isDebugEnabled()) { >+ log.debug("getSubjectDN(X509Certificate) - end; Ret is [" + subject + "]."); >+ } >+ return subject; >+ >+ } >+} >Index: org/apache/catalina/realm/RealmBase.java >=================================================================== >--- org/apache/catalina/realm/RealmBase.java (revision 1245889) >+++ org/apache/catalina/realm/RealmBase.java (working copy) >@@ -150,6 +150,26 @@ > protected boolean stripRealmForGss = true; > > >+ /** >+ * The <b>X509UserNameRetriever</b> is used to get the user name during the client certificate authentication >+ */ >+ private X509UserNameRetriever x509UserNameRetriever = null; >+ >+ >+ /** >+ * The value indicates which part of constitutes the username. >+ * The value is a code letter based on a legend defined in the certificate itself. >+ */ >+ >+ private String x509UserNameRetrieverConfiguration = null; >+ >+ /** >+ * @param className - the class that implements <b>X509UserNameRetriever</b> >+ * If the value is provided a realm will create X509UserNameRetriever. >+ * >+ */ >+ private String x509UserNameRetrieverClassName = null; >+ > // ------------------------------------------------------------- Properties > > >@@ -1034,6 +1054,8 @@ > if (container != null) { > this.containerLog = container.getLogger(); > } >+ // Create x509UserNameRetriever for the client certificate authentication. >+ createUserNameRetriever(x509UserNameRetrieverConfiguration, x509UserNameRetrieverClassName); > } > > /** >@@ -1191,7 +1213,12 @@ > * Return the Principal associated with the given certificate. > */ > protected Principal getPrincipal(X509Certificate usercert) { >- return(getPrincipal(usercert.getSubjectDN().getName())); >+ // get user name using x509UserNameRetriever >+ String userName = x509UserNameRetriever.getUserName(usercert); >+ >+ if (log.isDebugEnabled()) >+ log.debug("Get principal for [" + userName + "]"); >+ return(getPrincipal(userName)); > } > > >@@ -1390,5 +1417,104 @@ > return name; > } > } >+ >+ /** >+ * @param x509UserNameRetrieverConfiguration - the value is used to configure how to get the user name during the client certificate authentication. >+ * >+ * The user name is the unique part of information from the client certificate that used to identify the identity of the user. >+ * The Subject field (also called Subject Distinguish Name or SubjectDN) identifies the entity associated with the public key. >+ * The Subject field contains the following relevant attributes (it can also contain other attributes). >+ * >+ * Subject Attribute Subject Attribute Description Example >+ * CN Common Name CN=Bob BobFamily >+ * emailAddress Email Address emailAddress=bob@example.com >+ * C Country Name C=US >+ * ST State or Province Name ST=NY >+ * L Locality Name L=New York >+ * O Organization Name O=Work Organization >+ * OU Organizational Unit Name OU=Managers >+ * >+ * To retrieve the user name from the subject, you can use the entire SubjectDN field or the SubjectDN attribute. >+ * To retrieve the user name from entire SubjectDN field leave the value empty. >+ * To retrieve the user name from the SubjectDN attribute, please provide the retrieve attribute name. >+ * The the retrieve attribute name is a code letter based on a legend defined in the certificate itself. >+ * >+ * For example, the Email attribute is used to hold the User Name. >+ * Please provide "e" or "emailAddress" for the constructor. >+ * >+ * For example, the Common Name attribute is used to hold the User Name. >+ * Please provide "CN" for the constructor. >+ * >+ */ >+ public void setX509UserNameRetrieverConfiguration(String x509UserNameRetrieverConfiguration) { >+ this.x509UserNameRetrieverConfiguration = x509UserNameRetrieverConfiguration; >+ } > >+ /** >+ * @param className - The Java class name that is used to override the default <b>X509UserNameRetriever.</b> >+ * The X509UserNameRetriever is used to get the user name during the client certificate authentication. >+ * If the value is provided a realm will create X509UserNameRetriever from the provided class. >+ * This class must implement the <code>org.apache.catalina.realm.X509UserNameRetriever</code> interface. >+ */ >+ >+ public void setX509UserNameRetrieverClassName(String className) { >+ x509UserNameRetrieverClassName = className; >+ } >+ >+ >+ private void createUserNameRetriever(String x509UserNameRetrieverConfiguration, String x509UserNameRetrieverClassName) { >+ >+ boolean createdFromClassName = createUserNameRetrieverFromClassName(x509UserNameRetrieverClassName); >+ if (createdFromClassName) { >+ if (x509UserNameRetriever instanceof X509SubjectDnRetriever) { >+ // set the configuration to x509UserNameRetriever >+ ((X509SubjectDnRetriever) x509UserNameRetriever).setX509UserNameRetrieverConfiguration(x509UserNameRetrieverConfiguration); >+ } >+ } else { >+ if (x509UserNameRetrieverConfiguration == null) { >+ x509UserNameRetriever = new X509SubjectDnRetriever(); >+ } else { >+ x509UserNameRetriever = new X509SubjectDnRetriever(x509UserNameRetrieverConfiguration); >+ } >+ } >+ } >+ >+ >+ >+ @SuppressWarnings("unchecked") >+ private boolean createUserNameRetrieverFromClassName(String x509UserNameRetrieverClassName) { >+ >+ boolean created = false; >+ if ((x509UserNameRetrieverClassName != null) >+ && (x509UserNameRetrieverClassName != "")) { >+ Class<? extends X509UserNameRetriever> x509UserNameRetrieverClass = null; >+ try { >+ x509UserNameRetrieverClass = (Class<? extends X509UserNameRetriever>) Class.forName(x509UserNameRetrieverClassName); >+ x509UserNameRetriever = x509UserNameRetrieverClass.newInstance(); >+ created = true; >+ if (log.isDebugEnabled()) { >+ log.debug("Success to create x509UserNameRetriever [" + x509UserNameRetriever + "]."); >+ } >+ } catch (ClassCastException e) { >+ String warnString = "Class [" + x509UserNameRetrieverClassName + "] is not instance of [" + X509UserNameRetriever.class.getSimpleName() + "]."; >+ log.warn(warnString); >+ } catch (ClassNotFoundException e) { >+ String warnString = "Class [" + x509UserNameRetrieverClassName + "] was not found."; >+ log.warn(warnString, e); >+ } catch (InstantiationException e) { >+ String warnString = "Cannot instantiate class [" + x509UserNameRetrieverClassName + "]."; >+ log.warn(warnString); >+ } catch (IllegalAccessException e) { >+ String warnString = "Cannot instantiate class [" + x509UserNameRetrieverClassName + "]."; >+ log.warn(warnString); >+ } >+ } >+ return created; >+ } >+ >+ >+ >+ >+ >+ > } >Index: org/apache/catalina/realm/X509UserNameRetriever.java >=================================================================== >--- org/apache/catalina/realm/X509UserNameRetriever.java (revision 0) >+++ org/apache/catalina/realm/X509UserNameRetriever.java (revision 0) >@@ -0,0 +1,30 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You 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.apache.catalina.realm; >+ >+import java.security.cert.X509Certificate; >+ >+/** >+ * The interface <b>X509UserNameRetriever</b> defines how to retrieve a user name from X509Certificate. >+ * The user name is the unique part of information from the client certificate >+ * that used to identify the identity of the user. >+ * The interface is used to get the user name during the client certificate authentication >+ */ >+public interface X509UserNameRetriever { >+ String getUserName(X509Certificate clientCert); >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 52500
:
28190
|
28191
|
28199
|
28200
|
28237
|
28238
|
28308
|
28309
|
28348
|
28349
| 28386 |
28387
|
28450