import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.security.Principal; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.hyperion.css.CSSAPIIF; import com.hyperion.css.CSSException; import com.hyperion.css.CSSSecurityAgentIF; import com.hyperion.css.CSSSystem; import com.hyperion.css.common.CSSPrincipalIF; import com.hyperion.css.common.CSSUserIF; import com.hyperion.css.registry.RegistryManager; import com.hyperion.hit.registry.Component; import com.hyperion.hit.registry.ComponentType; import com.hyperion.hit.registry.Registry; import com.hyperion.hit.registry.exceptions.RegistryException; /** * CertificateAuthNSample is the certificate based authentication login class for CSS and itimplements the CSSSecurityAgentIF interface * This class accepts the X509 certificate of the authenticated user from the Web Server via a header variable, parses the certificate, extracts the Dn of the User and authenticates the user. */ public class CertificateAuthNSample implements CSSSecurityAgentIF { static final String IDENTITY_ATTR = "CN"; String g_userDN = null; String g_userName = null; /** * Returns the Username of the Autenticated user. This is the login name of the user, for example * demouser * @param HttpServletRequest req * @param HttpServletResponse res * @return username of the Authenticated user. * @see CSS API documentation for CSSSecurityAgentIF */ public String getUserName(HttpServletRequest req, HttpServletResponse res) throws Exception { String certStr = getCertificate(req); String sCert = prepareCertificate(certStr); //String userName = getUserNameFromCert(sCert); /* Authenticate with a CN */ parseCertificate(sCert); /* Authenticate if the Login Attribute is a DN */ String cssDN = prepareCSSUserDNFromCert(); g_userName = getCSSUserNameFromDN(cssDN); if (g_userName == null) { throw new Exception("User name not found"); } return g_userName; } /** * Passing null since this is a trusted Security agent authentication * @param HttpServletRequest req * @param HttpServletRequest res * @return null * @see CSS API documentation for CSSSecurityAgentIF */ public String getPassword(HttpServletRequest req, HttpServletResponse res) throws Exception { return null; } /** * Get the Certificate sent by the Web Server in the HYPCERT header. * This HEADER NAME WILL CHANGE TO CSS_CLIENT_CERT * @param HttpServletRequest request * @return string containing the value of the Header HYPCERT */ protected String getCertificate(HttpServletRequest request) { String cStr = request.getHeader("HYPCERT"); return cStr; } /** * First get the Trusted Services Key from Registry. Next authenticate to CSS as ProxyUser (admin). * It then invokes getUserByIdentity DN is constructed as ldap://DN=Cn=....?USER. * Finally get the Login name of the user and return * @param String containing the Fully qualified DN of the authenticated user. * @return Css login name of the user * */ protected String getCSSUserNameFromDN(String DN) { /* * Call getUserNameByIdentity * */ CSSUserIF cssUserObj = null; try { Map context = new HashMap(5); context.put(CSSAPIIF.LOCALE, new Locale("en", "US")); String logPath = "C:/Hyperion/logs/"; CSSSystem instance = CSSSystem.getInstance(context, logPath); CSSAPIIF css = instance.getCSSAPI(); // Host information (IP address/Host Name) is required for Auditing. context.put(CSSAPIIF.HOST_INFO, "arukum.aztec.hyperion.com"); /* Get the Trusted Service Key from Registry */ String FOUNDATION_SERVICES = ComponentType.SYSTEM9 + "/" + ComponentType.FOUNDATION_SERVICES_PRODUCT+"/"; Registry regInstance = Registry.getInstance(); Component component = (Component)regInstance.lookup(FOUNDATION_SERVICES + ComponentType.SHARED_SERVICES_PRODUCT); String cssTrustedServicesKey = component.getPropertyValue(RegistryManager.CSS_TRUSTED_SERVICES_KEY); String cssUserName = "admin"; /* Proxy login as Admin using the Registry Key */ CSSUserIF proxyUser = css.authenticateProxyUser(context, cssUserName, cssTrustedServicesKey); CSSPrincipalIF proxyAdminUserPrinc = proxyUser.getPrincipal(); /* Now get the User Identity using the DN */ cssUserObj = css.getUserByIdentity(context, proxyAdminUserPrinc, DN); } catch (CSSException csse) { csse.printStackTrace(); } catch (RegistryException re) { re.printStackTrace(); } return cssUserObj.getLoginName(); } /** * The Certificate sent over by the WebServer is in the form of a String. All newline and Carriage returns * are replaced by a WHite Space. This Method puts a "\n" in place of the Whitespace. Or else, X509Certificate * java API will fail to parse the certificate. * @param String containing the Base64 encoded certificate of the authenticated user. */ protected String prepareCertificate(String gString) { String foo = null; String boo = null; foo = gString.replace("-----BEGIN CERTIFICATE-----", ""); boo = foo.replace("-----END CERTIFICATE-----", ""); String certStrWithNL = "-----BEGIN CERTIFICATE-----" + boo.replace(" ", "\n") + "-----END CERTIFICATE-----" ; return certStrWithNL; } /** * Prepares the DN as CSS' getUserByIdentity expects it * @param none * @return returns the DN of the user in the format - e.g. ldap://DN=cn=demouser,ou=hyperion,dc=com?USER */ protected String prepareCSSUserDNFromCert() { String cssUserDN = "ldap://DN=" + g_userDN + "?USER"; return cssUserDN; } /* * Parse the certificate * 1. Create X509Certificate using the certificateFactory and the Certificate string passed to us by the WebServer * 2. Get the Subject Principal Object * 3. Set the g_userDN to the DN * 4. Parse the DN and get the username[cn=demouser] from the Principal object and set g_userName. * @param String containing the base64 encoded certificate of the end user. * * */ protected String parseCertificate(String sCertificate) { X509Certificate cert = null; String userID = null; //out.println("authenticateViaCert::hyplogin" + hyplogin); try { X509Certificate clientCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(sCertificate.getBytes("UTF-8"))); if (clientCert == null) { // System.out.println("clientCert is Null"); } //System.out.println("Cert::String Format::" + clientCert.toString()); //out.println("Cert::Subject DN::" + clientCert.getSubjectDN()); Principal princDN = clientCert.getSubjectDN(); String dnStr = princDN.getName(); g_userDN = dnStr; int idx = dnStr.indexOf(","); //System.out.println("Index is" + idx); userID = dnStr.substring(3, idx); g_userName = userID; //System.out.println("CN=" + userID); } catch (CertificateException ce) { ce.printStackTrace(); //out.println("authenticateViaCert::Exception::CertificateException"); } catch(UnsupportedEncodingException uee) { //out.println("authenticateViaCert::Exception::UnsupportedEncodingException"); } return userID; } //end of getUserNameFromCert /* * TODO Remove the HYPCERT header from the request object so the no one else gets the Certificate. */ private void ConsumeHeader() { } }// end of class