/** * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: SAMLUtilsCommon.java,v 1.4 2008/11/10 22:57:00 veiming Exp $ * */ package com.sun.identity.saml.common; import com.sun.identity.common.SystemConfigurationUtil; import com.sun.identity.saml.xmlsig.PasswordDecoder; import com.sun.identity.shared.encode.Base64; import com.sun.identity.shared.debug.Debug; import com.sun.identity.shared.locale.Locale; import java.util.ResourceBundle; import java.util.TimeZone; import java.security.SecureRandom; import org.w3c.dom.*; /** * This class contains a set of generic common utility methods. * */ public class SAMLUtilsCommon { private static String PASSWORD_DECODER = "com.sun.identity.saml.xmlsig.passwordDecoder"; private static String FM_PASSWORD_DECODER = "com.sun.identity.saml.xmlsig.FMPasswordDecoder"; /** * SecureRandom instance. */ public static SecureRandom random = new SecureRandom(); /** * Prefix for ids used in SAML service. */ public static final String SAMLID_PREFIX = "s"; /** * A handle for SAMLConstants. */ public static SAMLConstants sc; /** * SAML resource bundle object. */ public static ResourceBundle bundle = Locale.getInstallResourceBundle("libSAML"); /** * SAML debug object. */ public static Debug debug = Debug.getInstance("libSAML"); /** * Sets the ResourceBundle of the service. * @param resBundle ResourceBundle instance to be set. */ public static void setResourceBundle(ResourceBundle resBundle) { bundle = resBundle; } /** * Sets the Debug of the service. * @param dbg Debug instance to be set. */ public static void setDebugInstance(Debug dbg) { debug = dbg; } /** * Generates an ID String with length of SAMLConstants.ID_LENGTH. * @return string the ID String; or null if it fails. */ public static String generateAssertionID() { return generateID(); } /** * Generates an ID String with length of SAMLConstants.ID_LENGTH. * @return string the ID String; or null if it fails. */ public static String generateID() { if (random == null) { return null; } byte bytes[] = new byte[SAMLConstants.ID_LENGTH]; random.nextBytes(bytes); String encodedID = SAMLID_PREFIX + byteArrayToHexString(bytes); if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message( "SAMLUtils.generated ID is: " + encodedID); } return encodedID; } /** * Converts a byte array to a hex string. */ public static String byteArrayToHexString(byte[] byteArray) { int readBytes = byteArray.length; StringBuffer hexData = new StringBuffer(); int onebyte; for (int i=0; i < readBytes; i++) { onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); hexData.append(Integer.toHexString(onebyte).substring(6)); } return hexData.toString(); } /** * Generates end element tag. * It takes in the name of element and produces a String * as output which is in XML format. For example given * "SubjectConfirmation", It produces output like * </saml:SubjectConfirmation> * if includeNS is true else produces </SubjectConfirmation> * @param elementName name of an element * @param includeNS true to include namespace prefix; false otherwise. * @return String which is an xml element end tag. */ public static String makeEndElementTagXML(String elementName, boolean includeNS) { StringBuffer xml = new StringBuffer(100); String appendNS=""; if (includeNS) { appendNS="saml:"; } xml.append(sc.START_END_ELEMENT).append(appendNS).append(elementName). append(sc.RIGHT_ANGLE).append(sc.NL); return xml.toString(); } /** * Generates xml element start tag. * This utility method takes in the name fo element and produces a * String as output which is in XML format. For example given * "SubjectConfirmation". It produces output like * <saml:SubjectConfirmation xmlns:saml= * "http://www.oasis-open.org/committees/security/docs/ * draft-sstc-schema-assertion-16.xsd"> where nameSpace is defined in * AssertionBase class if declareNS and includeNS are true. * @param elementName name of the element. * @param includeNS true to include namespace prefix; false otherwise. * @param declareNS true to include namespace declaration; false otherwise. * @return xml element start tag. */ public static String makeStartElementTagXML(String elementName, boolean includeNS, boolean declareNS) { StringBuffer xml = new StringBuffer(1000); String appendNS=""; String NS=""; if (includeNS) { appendNS="saml:"; } if (declareNS) { NS = sc.assertionDeclareStr; } xml.append(sc.LEFT_ANGLE).append(appendNS).append(elementName). append(NS).append(sc.RIGHT_ANGLE); return xml.toString(); } /** * Verifies if an element is a type of a specific statement. * Currently, this method is used by class AuthenticationStatement, * AuthorizationDecisionStatement and AttributeStatement. * @param element a DOM Element which needs to be verified. * @param statementname A specific name of a statement, for example, * AuthenticationStatement, AuthorizationDecisionStatement or * AttributeStatement * @return true if the element is of the specified type; false otherwise. */ public static boolean checkStatement(Element element, String statementname){ String tag = element.getLocalName(); if (tag == null) { return false; } else if (tag.equals("Statement") || tag.equals("SubjectStatement")) { NamedNodeMap nm = element.getAttributes(); int len = nm.getLength(); String attrName = null; Attr attr = null; for (int j = 0; j < len; j++) { attr = (Attr) nm.item(j); attrName = attr.getLocalName(); if ((attrName != null) && (attrName.equals("type")) && (attr.getNodeValue().equals(statementname + "Type"))) { return true; } } } else if (tag.equals(statementname)) { return true; } return false; } /** * Decodes a password. * The value passed is the value to be decoded using the decoder class * defined in FederationConfig.properties. The decoded value * will be returned unless the decoder class is not defined, or cannot * be located. In that case, the original value will be returned. * * @param password original password. * @return decoded password. */ public static String decodePassword(String password) { String decodePwdSpi = SystemConfigurationUtil.getProperty( PASSWORD_DECODER, FM_PASSWORD_DECODER); String decoPasswd; try { PasswordDecoder pwdDecoder = (PasswordDecoder) Class.forName(decodePwdSpi).newInstance(); decoPasswd = pwdDecoder.getDecodedPassword(password); } catch (Throwable t) { decoPasswd = password; } return decoPasswd; } /** * Removes new line charactors. * @param s A String to be checked. * @return a String with new line charactor removed. */ public static String removeNewLineChars(String s) { String retString = null; if ((s != null) && (s.length() > 0) && (s.indexOf('\n') != -1)) { char[] chars = s.toCharArray(); int len = chars.length; StringBuffer sb = new StringBuffer(len); for (int i = 0; i < len; i++) { char c = chars[i]; if (c != '\n') { sb.append(c); } } retString = sb.toString(); } else { retString = s; } return retString; } /** * Decodes the Base64 encoded sourceid and returns * a String of the raw-byte source id. * * @param encodedID A String representing the Base64 encoded source id. * @return A String representing the raw byte source id. * */ public static String getDecodedSourceIDString(String encodedID) { String result = null; if (encodedID == null) { SAMLUtils.debug.error("SAMLUtils.getDecodedSourceIDString: null " + "input."); return null; } try { result = byteArrayToString(Base64.decode(encodedID)); } catch (Exception e) { SAMLUtils.debug.error("SAMLUtils.getDecodedSourceIDString: ", e); return null; } return result; } /** * Converts byte array to string. * @param bytes byte array to be converted. * @return result string. */ public static String byteArrayToString(byte[] bytes) { char chars[] = new char[bytes.length]; for (int i = 0; i < bytes.length; i++) { chars[i] = (char) bytes[i]; } return new String(chars); } }