Java tutorial
/* * Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. 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.wso2.carbon.hostobjects.sso.internal.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; import java.util.Random; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opensaml.Configuration; import org.opensaml.DefaultBootstrap; import org.opensaml.saml2.core.Response; import org.opensaml.xml.ConfigurationException; import org.opensaml.xml.XMLObject; import org.opensaml.xml.XMLObjectBuilder; import org.opensaml.xml.io.Marshaller; import org.opensaml.xml.io.MarshallerFactory; import org.opensaml.xml.io.Unmarshaller; import org.opensaml.xml.io.UnmarshallerFactory; import org.opensaml.xml.signature.SignatureValidator; import org.opensaml.xml.util.Base64; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.w3c.dom.bootstrap.DOMImplementationRegistry; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSOutput; import org.w3c.dom.ls.LSSerializer; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.core.util.KeyStoreManager; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; public class Util { private static boolean bootStrapped = false; private static Random random = new Random(); private static RealmService realmService = null; private static final char[] charMapping = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' }; private static Log log = LogFactory.getLog(Util.class); /** * This method is used to initialize the OpenSAML2 library. It calls the bootstrap method, if it * is not initialized yet. */ public static void doBootstrap() { if (!bootStrapped) { try { DefaultBootstrap.bootstrap(); bootStrapped = true; } catch (ConfigurationException e) { System.err.println("Error in bootstrapping the OpenSAML2 library"); e.printStackTrace(); } } } public static XMLObject buildXMLObject(QName objectQName) throws Exception { XMLObjectBuilder builder = org.opensaml.xml.Configuration.getBuilderFactory().getBuilder(objectQName); if (builder == null) { throw new Exception("Unable to retrieve builder for object QName " + objectQName); } return builder.buildObject(objectQName.getNamespaceURI(), objectQName.getLocalPart(), objectQName.getPrefix()); } /** * Generates a unique Id for Authentication Requests * * @return generated unique ID */ public static String createID() { byte[] bytes = new byte[20]; // 160 bits random.nextBytes(bytes); char[] chars = new char[40]; for (int i = 0; i < bytes.length; i++) { int left = (bytes[i] >> 4) & 0x0f; int right = bytes[i] & 0x0f; chars[i * 2] = charMapping[left]; chars[i * 2 + 1] = charMapping[right]; } return String.valueOf(chars); } /** * Constructing the XMLObject Object from a String * * @param authReqStr * @return Corresponding XMLObject which is a SAML2 object * @throws Exception */ public static XMLObject unmarshall(String authReqStr) throws Exception { try { doBootstrap(); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = docBuilder.parse(new ByteArrayInputStream(authReqStr.trim().getBytes())); Element element = document.getDocumentElement(); UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory(); Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(element); return unmarshaller.unmarshall(element); } catch (Exception e) { throw new Exception("Error in constructing AuthRequest from " + "the encoded String ", e); } } /** * Serializing a SAML2 object into a String * * @param xmlObject object that needs to serialized. * @return serialized object * @throws Exception */ public static String marshall(XMLObject xmlObject) throws Exception { try { doBootstrap(); System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory(); Marshaller marshaller = marshallerFactory.getMarshaller(xmlObject); Element element = marshaller.marshall(xmlObject); ByteArrayOutputStream byteArrayOutputStrm = new ByteArrayOutputStream(); DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS"); LSSerializer writer = impl.createLSSerializer(); LSOutput output = impl.createLSOutput(); output.setByteStream(byteArrayOutputStrm); writer.write(element, output); return byteArrayOutputStrm.toString(); } catch (Exception e) { throw new Exception("Error Serializing the SAML Response", e); } } /** * Compressing and Encoding the response * * @param xmlString String to be encoded * @return compressed and encoded String */ public static String encode(String xmlString) throws Exception { // Encoding the compressed message String encodedRequestMessage = Base64.encodeBytes(xmlString.getBytes("UTF-8"), Base64.DONT_BREAK_LINES); return encodedRequestMessage.trim(); } /** * Decoding and deflating the encoded AuthReq * * @param encodedStr encoded AuthReq * @return decoded AuthReq */ public static String decode(String encodedStr) throws Exception { return new String(Base64.decode(encodedStr)); } /** * This method validates the signature of the SAML Response. * @param resp SAML Response * @return true, if signature is valid. */ public static boolean validateSignature(Response resp, String keyStoreName, String keyStorePassword, String alias, int tenantId, String tenantDomain) { boolean isSigValid = false; try { KeyStore keyStore = null; java.security.cert.X509Certificate cert = null; if (tenantId != MultitenantConstants.SUPER_TENANT_ID) { // get an instance of the corresponding Key Store Manager instance KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); keyStore = keyStoreManager.getKeyStore(generateKSNameFromDomainName(tenantDomain)); cert = (java.security.cert.X509Certificate) keyStore.getCertificate(tenantDomain); } else { keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream(new File(keyStoreName)), keyStorePassword.toCharArray()); cert = (java.security.cert.X509Certificate) keyStore.getCertificate(alias); } if (log.isDebugEnabled()) { log.debug("Validating against " + cert.getSubjectDN().getName()); } X509CredentialImpl credentialImpl = new X509CredentialImpl(cert); SignatureValidator signatureValidator = new SignatureValidator(credentialImpl); signatureValidator.validate(resp.getSignature()); isSigValid = true; return isSigValid; } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Signature verification is failed for " + tenantDomain); } return isSigValid; } } public static String getDomainName(XMLObject samlObject) { NodeList list = samlObject.getDOM().getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "NameID"); String domainName = null; if (list.getLength() > 0) { String userName = list.item(0).getTextContent(); domainName = MultitenantUtils.getTenantDomain(userName); } return domainName; } /** * Generate the key store name from the domain name * @param tenantDomain tenant domain name * @return key store file name */ private static String generateKSNameFromDomainName(String tenantDomain) { String ksName = tenantDomain.trim().replace(".", "-"); return (ksName + ".jks"); } public static void setRealmService(RealmService realmService) { Util.realmService = realmService; } public static RealmService getRealmService() { return Util.realmService; } }