001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: SAML2SDKUtils.java,v 1.12 2008/08/31 05:49:48 bina Exp $ 026 * 027 */ 028 029 030package com.sun.identity.saml2.common; 031 032import com.sun.identity.liberty.ws.disco.ResourceOffering; 033import com.sun.identity.liberty.ws.security.SecurityAssertion; 034import com.sun.identity.plugin.session.SessionManager; 035import com.sun.identity.plugin.session.SessionProvider; 036import com.sun.identity.saml.common.SAMLConstants; 037import com.sun.identity.saml.common.SAMLUtilsCommon; 038import com.sun.identity.saml2.jaxb.entityconfig.BaseConfigType; 039import com.sun.identity.saml2.meta.SAML2MetaUtils; 040import com.sun.identity.shared.configuration.SystemPropertiesManager; 041import com.sun.identity.shared.debug.Debug; 042import com.sun.identity.shared.locale.Locale; 043import com.sun.identity.shared.xml.XMLUtils; 044import java.security.SecureRandom; 045import java.lang.reflect.Constructor; 046import java.lang.reflect.InvocationTargetException; 047import java.util.ArrayList; 048import java.util.HashMap; 049import java.util.List; 050import java.util.Map; 051import java.util.ResourceBundle; 052import javax.servlet.http.HttpServletRequest; 053import org.w3c.dom.Attr; 054import org.w3c.dom.Element; 055import org.w3c.dom.NamedNodeMap; 056import javax.xml.soap.SOAPException; 057 058/** 059 * The <code>SAML2SDKUtils</code> contains utility methods for SAML 2.0 060 * implementation. 061 * 062 * @supported.all.api 063 */ 064public class SAML2SDKUtils { 065 // 066 // This utility class will be run on client side as well, 067 // so DO NOT add any static block which will not run on client side. 068 // 069 // The deugging instance 070 public static Debug debug = Debug.getInstance("libSAML2"); 071 // SAML2 Resource bundle 072 public static final String BUNDLE_NAME = "libSAML2"; 073 // The resource bundle for SAML 2.0 implementation. 074 public static ResourceBundle bundle = Locale. 075 getInstallResourceBundle(BUNDLE_NAME); 076 protected static final String SAML2ID_PREFIX = "s2"; 077 public static SecureRandom random = new SecureRandom(); 078 079 /** 080 * Defines mapping between interface and implementation class, 081 * the properties are read from AMConfig.properties in following format: 082 * com.sun.identity.saml2.sdk.mapping.<interface>=<implementation_class> 083 * e.g. 084 * com.sun.identity.saml2.sdk.mapping.Assertion=com.xxx.saml2.AssertionImpl 085 */ 086 private static Map classMapping = new HashMap(); 087 088 // define constants for the interface names 089 public static final String ACTION = "Action"; 090 public static final String ADVICE = "Advice"; 091 public static final String ASSERTION = "Assertion"; 092 public static final String ASSERTION_ID_REF = "AssertionIDRef"; 093 public static final String ASSERTION_ID_REQUEST = "AssertionIDRequest"; 094 public static final String ATTRIBUTE = "Attribute"; 095 public static final String ATTRIBUTE_STATEMENT = "AttributeStatement"; 096 public static final String AUDIENCE_RESTRICTION = "AudienceRestriction"; 097 public static final String AUTHN_CONTEXT = "AuthnContext"; 098 public static final String AUTHN_STATEMENT = "AuthnStatement"; 099 public static final String AUTHZ_DECISION_STATEMENT = 100 "AuthzDecisionStatement"; 101 public static final String BASEID = "BaseID"; 102 public static final String CONDITION = "Condition"; 103 public static final String CONDITIONS = "Conditions"; 104 public static final String ENCRYPTED_ASSERTION = "EncryptedAssertion"; 105 public static final String ENCRYPTED_ATTRIBUTE = "EncryptedAttribute"; 106 public static final String ENCRYPTED_ELEMENT = "EncryptedElement"; 107 public static final String ENCRYPTEDID = "EncryptedID"; 108 public static final String EVIDENCE = "Evidence"; 109 public static final String ISSUER = "Issuer"; 110 public static final String KEYINFO_CONFIRMATION_DATA = 111 "KeyInfoConfirmationData"; 112 public static final String NAMEID = "NameID"; 113 public static final String ONE_TIME_USE = "OneTimeUse"; 114 public static final String PROXY_RESTRICTION = "ProxyRestriction"; 115 public static final String STATEMENT = "Statement"; 116 public static final String SUBJECT_CONFIRMATION_DATA = 117 "SubjectConfirmationData"; 118 public static final String SUBJECT_CONFIRMATION = "SubjectConfirmation"; 119 public static final String SUBJECT = "Subject"; 120 public static final String SUBJECT_LOCALITY = "SubjectLocality"; 121 public static final String ARTIFACT = "Artifact"; 122 public static final String ARTIFACT_RESOLVE = "ArtifactResolve"; 123 public static final String ARTIFACT_RESPONSE = "ArtifactResponse"; 124 public static final String ATTRIBUTE_QUERY = "AttributeQuery"; 125 public static final String AUTHN_QUERY = "AuthnQuery"; 126 public static final String AUTHN_REQUEST = "AuthnRequest"; 127 public static final String ECP_RELAY_STATE = "ECPRelayState"; 128 public static final String ECP_REQUEST = "ECPRequest"; 129 public static final String ECP_RESPONSE = "ECPResponse"; 130 public static final String EXTENSIONS = "Extensions"; 131 public static final String GET_COMPLETE = "GetComplete"; 132 public static final String IDPENTRY = "IDPEntry"; 133 public static final String IDPLIST = "IDPList"; 134 public static final String LOGOUT_REQUEST = "LogoutRequest"; 135 public static final String LOGOUT_RESPONSE = "LogoutResponse"; 136 public static final String MANAGE_NAMEID_REQUEST = "ManageNameIDRequest"; 137 public static final String MANAGE_NAMEID_RESPONSE = "ManageNameIDResponse"; 138 public static final String NAMEID_POLICY = "NameIDPolicy"; 139 public static final String NEW_ENCRYPTEDID = "NewEncryptedID"; 140 public static final String NEWID = "NewID"; 141 public static final String REQUESTED_AUTHN_CONTEXT = 142 "RequestedAuthnContext"; 143 public static final String REQUESTERID = "RequesterID"; 144 public static final String RESPONSE = "Response"; 145 public static final String SCOPING = "Scoping"; 146 public static final String SESSION_INDEX = "SessionIndex"; 147 public static final String STATUS_CODE = "StatusCode"; 148 public static final String STATUS_DETAIL = "StatusDetail"; 149 public static final String STATUS = "Status"; 150 public static final String STATUS_MESSAGE = "StatusMessage"; 151 public static final String STATUS_RESPONSE = "StatusResponse"; 152 public static final String NAMEIDMAPPING_REQ = "NameIDMappingRequest"; 153 public static final String NAMEIDMAPPING_RES = "NameIDMappingResponse"; 154 155 /** 156 * List of Interfaces in assertion and protocol packages which could have 157 * customized implementation 158 */ 159 private static String[] interfactNames = { 160 ACTION, ADVICE, ASSERTION, ASSERTION_ID_REF, ASSERTION_ID_REQUEST, 161 ATTRIBUTE, ATTRIBUTE_STATEMENT, AUDIENCE_RESTRICTION, AUTHN_CONTEXT, 162 AUTHN_STATEMENT, AUTHZ_DECISION_STATEMENT, BASEID, 163 CONDITION, CONDITIONS, ENCRYPTED_ASSERTION, 164 ENCRYPTED_ATTRIBUTE, ENCRYPTED_ELEMENT, ENCRYPTEDID, EVIDENCE, 165 ISSUER, KEYINFO_CONFIRMATION_DATA, NAMEID, 166 ONE_TIME_USE, PROXY_RESTRICTION, STATEMENT, 167 SUBJECT_CONFIRMATION_DATA, SUBJECT_CONFIRMATION, SUBJECT, 168 SUBJECT_LOCALITY, ARTIFACT, ARTIFACT_RESOLVE, ARTIFACT_RESPONSE, 169 ATTRIBUTE_QUERY, AUTHN_QUERY, AUTHN_REQUEST, EXTENSIONS, GET_COMPLETE, 170 IDPENTRY, IDPLIST, LOGOUT_REQUEST, LOGOUT_RESPONSE, 171 MANAGE_NAMEID_REQUEST, MANAGE_NAMEID_RESPONSE, NAMEID_POLICY, 172 NEW_ENCRYPTEDID, NEWID, REQUESTED_AUTHN_CONTEXT, REQUESTERID, RESPONSE, 173 SCOPING, SESSION_INDEX, STATUS_CODE, STATUS_DETAIL, STATUS, 174 STATUS_MESSAGE, STATUS_RESPONSE, NAMEIDMAPPING_REQ, NAMEIDMAPPING_RES}; 175 176 /** 177 * Class array for Artifact constructor 178 */ 179 private static Class[] artParam = new Class[] { (new byte[2]).getClass(), 180 int.class, String.class, String.class }; 181 182 /** 183 * Class array for String as parameter 184 */ 185 private static Class[] stringParam = new Class[] {String.class}; 186 187 /** 188 * Class array for Element as parameter 189 */ 190 private static Class[] elementParam = new Class[] {Element.class}; 191 192 static { 193 // initialize class mapper 194 int len = interfactNames.length; 195 for (int i = 0; i < len; i++) { 196 String iName = interfactNames[i]; 197 try { 198 String implClass = SystemPropertiesManager.get( 199 SAML2Constants.SDK_CLASS_MAPPING + iName); 200 if (implClass != null && implClass.trim().length() != 0) { 201 // try it out 202 if (debug.messageEnabled()) { 203 debug.message("SAML2SDKUtils.init: mapper for " + iName 204 + "=" + implClass); 205 } 206 classMapping.put(iName, Class.forName(implClass.trim())); 207 } 208 } catch (ClassNotFoundException cnfe) { 209 debug.error("SAML2SDKUtils.init: " + iName, cnfe); 210 } 211 } 212 } 213 214 /** 215 * Protected contstructor. 216 */ 217 protected SAML2SDKUtils() {} 218 219 /** 220 * Returns default object instance for a given interface. 221 * @param iName name of the interface. 222 * @return object instance corresponding to the interface implementation. 223 * return null if the object instance could not be obtained. 224 */ 225 public static Object getObjectInstance(String iName) { 226 Class implClass = (Class) classMapping.get(iName); 227 if (implClass == null) { 228 return null; 229 } else { 230 try { 231 return implClass.newInstance(); 232 } catch (InstantiationException ie) { 233 debug.error("SAML2SDKUtils.getDefaultInstance: " + iName, ie); 234 } catch (IllegalAccessException iae) { 235 debug.error("SAML2SDKUtils.getDefaultInstance: " + iName, iae); 236 } 237 return null; 238 } 239 } 240 241 /** 242 * Returns new object instance taking String parameter in constructor. 243 * @param iName name of the interface. 244 * @param value String value to be used as parameter in constructor. 245 * @return object instance corresponding to the interface implementation. 246 * return null if the object instance could not be obtained. 247 */ 248 public static Object getObjectInstance(String iName, String value){ 249 Class implClass = (Class) classMapping.get(iName); 250 if (implClass == null) { 251 return null; 252 } else { 253 if (debug.messageEnabled()) { 254 debug.message("SAML2SDKUtils.getObjectInstance: new customized " 255 + "impl (String) instance for " + iName); 256 } 257 Object[] params = new Object[] { value }; 258 return getObjectInstance(implClass, stringParam, params); 259 } 260 } 261 262 /** 263 * Returns new object instance taking Element parameter in constructor. 264 * @param iName name of the interface. 265 * @param value Element value to be used as parameter in constructor. 266 * @return object instance corresponding to the interface implementation. 267 * return null if the object instance could not be obtained. 268 */ 269 public static Object getObjectInstance(String iName, Element value) { 270 Class implClass = (Class) classMapping.get(iName); 271 if (implClass == null) { 272 return null; 273 } else { 274 if (debug.messageEnabled()) { 275 debug.message("SAML2SDKUtils.getObjectInstance: new customized " 276 + "impl instance (Element) for " + iName); 277 } 278 Object[] params = new Object[] { value }; 279 return getObjectInstance(implClass, elementParam, params); 280 } 281 } 282 283 /** 284 * Returns new object instance with given parameters. 285 * @param iName name of the interface. 286 * @param typecode type code. 287 * @param endpointIndex end point index. 288 * @param sourceID source ID. 289 * @param messageHandle message handler. 290 * @return object instance corresponding to the interface implementation. 291 * return null if the object instance could not be obtained. 292 */ 293 294 public static Object getObjectInstance(String iName, byte[] typecode, 295 int endpointIndex, String sourceID, String messageHandle) { 296 Class implClass = (Class) classMapping.get(iName); 297 if (implClass == null) { 298 return null; 299 } else { 300 if (debug.messageEnabled()) { 301 debug.message("SAML2SDKUtils.getObjectInstance: new customized " 302 + "impl (4) instance for " + iName); 303 } 304 Object[] params = new Object[] 305 { typecode, new Integer(endpointIndex), 306 sourceID, messageHandle }; 307 return getObjectInstance(implClass, artParam, params); 308 } 309 } 310 311 312 /** 313 * Returns new object instance with given parameter in constructor. 314 * @param impl Class instance. 315 * @param paramObj Class array for constructor parameters. 316 * @param valueObj Object array for values of constructor parameters. 317 * @return object instance corresponding to the interface implementation. 318 * return null if the object instance could not be obtained. 319 */ 320 private static Object getObjectInstance(Class impl, 321 Class[] paramObj, Object[] valueObj) { 322 try { 323 Constructor constr = impl.getConstructor(paramObj); 324 return constr.newInstance(valueObj); 325 } catch (NoSuchMethodException nsme) { 326 debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 327 nsme); 328 } catch (SecurityException se) { 329 debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 330 se); 331 } catch (InstantiationException ie) { 332 debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 333 ie); 334 } catch (IllegalAccessException iae) { 335 debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 336 iae); 337 } catch (IllegalArgumentException iae) { 338 debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 339 iae); 340 } catch (InvocationTargetException ite) { 341 debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 342 ite); 343 } 344 return null; 345 } 346 347 /** 348 * Verifies if an element is a type of a specific statement. 349 * Currently, this method is used by class AuthnStatementImpl, 350 * AuthzDecisionStatement and AttributeStatementImpl. 351 * @param element a DOM Element which needs to be verified. 352 * @param statementname A specific name of a statement, for example, 353 * AuthnStatement, AuthzStatement or AttributeStatement 354 * @return <code>true</code> if the element is of the specific type; 355 * <code>false</code> otherwise. 356 */ 357 public static boolean checkStatement(Element element, String statementname){ 358 if (element == null || statementname == null) { 359 return false; 360 } 361 362 String tag = element.getLocalName(); 363 if (tag == null) { 364 return false; 365 } else if (tag.equals("Statement")) { 366 NamedNodeMap nm = element.getAttributes(); 367 int len = nm.getLength(); 368 String attrName = null; 369 Attr attr = null; 370 for (int j = 0; j < len; j++) { 371 attr = (Attr) nm.item(j); 372 attrName = attr.getLocalName(); 373 if ((attrName != null) && (attrName.equals("type")) && 374 (attr.getNodeValue().equals(statementname + "Type"))) { 375 return true; 376 } 377 } 378 } else if (tag.equals(statementname)) { 379 return true; 380 } 381 return false; 382 } 383 384 /** 385 * Converts byte array to String. 386 * 387 * @param bytes Byte Array to be converted. 388 * @return result of the conversion. 389 */ 390 public static String byteArrayToString(byte[] bytes) { 391 char chars[] = new char[bytes.length]; 392 for (int i = 0; i < bytes.length; i++) { 393 chars[i] = (char) bytes[i]; 394 } 395 return new String(chars); 396 } 397 398 /** 399 * Converts integer to byte array. 400 * 401 * @param i an integer value between 0 and 65535. 402 * @return a byte array whose length is 2. 403 * @throws SAML2Exception if the input is not between 0 and 65535. 404 */ 405 public static byte[] intToTwoBytes(int i) 406 throws SAML2Exception { 407 if (i < 0 || i > 65535) { 408 debug.error("SAML2Utils.intToTwoBytes: wrong index value range."); 409 throw new SAML2Exception( 410 bundle.getString("wrongInput")); 411 } 412 413 String hexStr = Integer.toHexString(i); 414 415 //System.out.println("Original="+hexStr); 416 417 int len = hexStr.length(); 418 String norm = null; 419 if (len > 4) { 420 norm = hexStr.substring(0,4); 421 } else { 422 switch (len) { 423 case 1: 424 norm = "000"+hexStr; 425 break; 426 case 2: 427 norm = "00"+hexStr; 428 break; 429 case 3: 430 norm = "0"+hexStr; 431 break; 432 default: 433 norm = hexStr; 434 } 435 } 436 437 byte[] bytes = hexStringToByteArray(norm); 438 439 return bytes; 440 } 441 442 /** 443 * Converts two bytes to an integer. 444 * 445 * @param bytes byte array whose length is 2. 446 * @return an integer value between 0 and 65535. 447 * @throws SAML2Exception if the input is null or the length is not 2. 448 */ 449 public static int twoBytesToInt(byte[] bytes) 450 throws SAML2Exception { 451 if (bytes == null || bytes.length != 2) { 452 debug.error("SAML2Utils.twoBytesToInt: input is null or length is " 453 + "not 2."); 454 throw new SAML2Exception(bundle.getString("wrontInput")); 455 } 456 457 String str0 = Integer.toHexString(bytes[0]); 458 int len0 = str0.length(); 459 String norm0 = null; 460 if (len0 > 2) { 461 norm0 = str0.substring(len0-2, len0); 462 } else { 463 norm0 = str0; 464 } 465 String str1 = Integer.toHexString(bytes[1]); 466 int len1 = str1.length(); 467 String norm1 = null; 468 if (len1 > 2) { 469 norm1 = str1.substring(len1-2, len1); 470 } else if (len1 == 1) { 471 norm1 = "0"+str1; 472 } else { 473 norm1 = str1; 474 } 475 476 String wholeHexStr = norm0+norm1; 477 478 int i = Integer.parseInt(wholeHexStr, 16); 479 480 return i; 481 } 482 483 /** 484 * Generates message handle used in an <code>Artifact</code>. 485 * 486 * @return String format of 20-byte sequence identifying 487 * a message. 488 */ 489 public static String generateMessageHandle() { 490 if (random == null) { 491 return null; 492 } 493 byte bytes[] = new byte[SAML2Constants.ID_LENGTH]; 494 random.nextBytes(bytes); 495 return byteArrayToString(bytes); 496 } 497 498 /** 499 * Converts String to Byte Array. 500 * 501 * @param input String to be converted. 502 * @return result of the conversion. 503 */ 504 public static byte[] stringToByteArray(String input) { 505 char chars[] = input.toCharArray(); 506 byte bytes[] = new byte[chars.length]; 507 for (int i = 0; i < chars.length; i++) { 508 bytes[i] = (byte) chars[i]; 509 } 510 return bytes; 511 } 512 513 /** 514 * Converts byte array to <code>Hex</code> String. 515 * 516 * @param byteArray Byte Array to be converted. 517 * @return result of the conversion. 518 */ 519 public static String byteArrayToHexString(byte[] byteArray) { 520 int readBytes = byteArray.length; 521 StringBuffer hexData = new StringBuffer(); 522 int onebyte; 523 for (int i=0; i < readBytes; i++) { 524 onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); 525 hexData.append(Integer.toHexString(onebyte).substring(6)); 526 } 527 return hexData.toString(); 528 } 529 530 /** 531 * Converts <code>Hex</code> String to Byte Array. 532 * 533 * @param hexString <code>Hex</code> String to be converted. 534 * @return result of the conversion. 535 */ 536 public static byte[] hexStringToByteArray(String hexString) { 537 int read = hexString.length(); 538 byte[] byteArray = new byte[read/2]; 539 for (int i=0, j=0; i < read; i++, j++) { 540 String part = hexString.substring(i,i+2); 541 byteArray[j] = 542 new Short(Integer.toString(Integer.parseInt(part,16))). 543 byteValue(); 544 i++; 545 } 546 return byteArray; 547 } 548 549 /** 550 * Generates ID. 551 * @return ID value. 552 */ 553 public static String generateID() { 554 if (random == null) { 555 return null; 556 } 557 byte bytes[] = new byte[SAML2Constants.ID_LENGTH]; 558 random.nextBytes(bytes); 559 return (SAML2ID_PREFIX + byteArrayToHexString(bytes)); 560 } 561 562 /** 563 * Gets the Discovery bootstrap resource offering in an attribute 564 * statement. After a single sign-on with an Identity Provider, a service 565 * provider may get Discovery service esource Offerings through a SAML2 566 * assertion. This APIs helps in retrieving the resource offerings 567 * if the user has been authenticated through the SAML2 SSO. It will 568 * need to have a valid single sign on token (generated through the 569 * SAML2 SSO). 570 * 571 * @param request <code>HttpServletRequest</code> associated with a user 572 * session. 573 * @return <code>ResourceOffering</code> Discovery Resource Offering, 574 * null if there is any failure or if there is not one 575 */ 576 public static ResourceOffering getDiscoveryBootStrapResourceOffering( 577 HttpServletRequest request) { 578 579 if (request == null) { 580 if (debug.messageEnabled()) { 581 debug.message("SAML2Utils.getDiscoveryBootStrapResource" + 582 "Offerings: null Input params"); 583 } 584 return null; 585 } 586 try { 587 SessionProvider sessionProvider = SessionManager.getProvider(); 588 Object session = sessionProvider.getSession(request); 589 590 String[] roStr = sessionProvider.getProperty(session, 591 SAML2Constants.DISCOVERY_BOOTSTRAP_ATTRIBUTE_NAME); 592 if ((roStr == null) || (roStr.length == 0)) { 593 return null; 594 } 595 596 return new ResourceOffering( 597 XMLUtils.toDOMDocument(roStr[0], debug).getDocumentElement()); 598 599 } catch(Exception ex) { 600 debug.error("SAML2Utils.getDiscoveryBootStrapResourceOfferings: " + 601 " Exception while retrieving discovery boot strap info.", ex); 602 return null; 603 } 604 605 } 606 607 /** 608 * Gets the Discovery bootstrap credentials. 609 * After a single sign-on with an Identity Provider, a service 610 * provider may get Discovery bootstrap resource offerings and credentials 611 * through a SAML assertion. This APIs helps in retrieving the credentials 612 * if the user has been authenticated through the SAML2 SSO. It will 613 * need to have a valid single sign on token (generated through the 614 * SAML2 SSO). 615 * 616 * @param request <code>HttpServletRequest</code> associated with a user 617 * session. 618 * @return <code>List</code> of <code>SecurityAssertions</code>, 619 * null if there is any failure or if there is not one 620 */ 621 public static List getDiscoveryBootStrapCredentials( 622 HttpServletRequest request) { 623 624 if (request == null) { 625 if (debug.messageEnabled()) { 626 debug.message("SAML2Utils.getDiscoveryBootStrapCredentials: " + 627 " null Input params"); 628 } 629 return null; 630 } 631 try { 632 SessionProvider sessionProvider = SessionManager.getProvider(); 633 Object session = sessionProvider.getSession(request); 634 String[] credentials = sessionProvider.getProperty(session, 635 SAML2Constants.DISCOVERY_BOOTSTRAP_CREDENTIALS); 636 if ((credentials == null) || (credentials.length == 0)) { 637 return null; 638 } 639 640 List securityAssertions = new ArrayList(); 641 for(int i=0; i< credentials.length; i++) { 642 SecurityAssertion securityAssertion = new SecurityAssertion( 643 XMLUtils.toDOMDocument(credentials[i], debug) 644 .getDocumentElement()); 645 securityAssertions.add(securityAssertion); 646 } 647 return securityAssertions; 648 } catch(Exception ex) { 649 debug.error("SAML2Utils.getDiscoveryBootStrapCredentials: ", ex); 650 return null; 651 } 652 } 653 654 /** 655 * Creates <code>SOAPMessage</code> with the input XML String 656 * as message body. 657 * @param xmlString XML string to be put into <code>SOAPMessage</code> body. 658 * @return newly created <code>SOAPMessage</code>. 659 * @exception SOAPException if it cannot create the 660 * <code>SOAPMessage</code>. 661 */ 662 public static String createSOAPMessageString(String xmlString) 663 throws SOAPException, SAML2Exception { 664 StringBuffer sb = new StringBuffer(500); 665 if (debug.messageEnabled()) { 666 debug.message("SAML2Utils.createSOAPMessage: xmlstr = " + 667 xmlString); 668 } 669 sb.append("<").append(SAMLConstants.SOAP_ENV_PREFIX). 670 append(":Envelope").append(SAMLConstants.SPACE). 671 append("xmlns:").append(SAMLConstants.SOAP_ENV_PREFIX). 672 append("=\"").append(SAMLConstants.SOAP_URI).append("\">"). 673 append("<"). 674 append(SAMLConstants.SOAP_ENV_PREFIX).append(":Body>"). 675 append(xmlString). 676 append(SAMLConstants.START_END_ELEMENT). 677 append(SAMLConstants.SOAP_ENV_PREFIX). 678 append(":Body>"). 679 append(SAMLConstants.START_END_ELEMENT). 680 append(SAMLConstants.SOAP_ENV_PREFIX). 681 append(":Envelope>").append(SAMLConstants.NL); 682 683 if (debug.messageEnabled()) { 684 debug.message("SAML2Utils.createSOAPMessage: soap message = " + 685 sb.toString()); 686 } 687 return sb.toString(); 688 } 689 690 691 /** 692 * Fills in basic auth user and password inside the location URL 693 * if configuration is done properly 694 * @param config Either an SPSSOConfigElement object , an 695 * IDPSSOConfigElement object or PEPConfigElement. 696 * @param locationURL The original location URL which is to be 697 * inserted with user:password@ before the 698 * hostname part and after // 699 * @return The modified location URL with the basic auth user 700 * and password if configured properly 701 */ 702 public static String fillInBasicAuthInfo( 703 BaseConfigType config, 704 String locationURL) { 705 706 if (config == null) { 707 return locationURL; 708 } 709 Map map = SAML2MetaUtils.getAttributes(config); 710 List baoList = (List)map.get( 711 SAML2Constants.BASIC_AUTH_ON); 712 if (baoList == null || baoList.isEmpty()) { 713 return locationURL; 714 } 715 String on = (String)baoList.get(0); 716 if (on == null) { 717 return locationURL; 718 } 719 on = on.trim(); 720 if (on.length() == 0 || !on.equalsIgnoreCase("true")) { 721 return locationURL; 722 } 723 List ul = (List)map.get( 724 SAML2Constants.BASIC_AUTH_USER); 725 726 if (ul == null || ul.isEmpty()) { 727 return locationURL; 728 } 729 String u = (String) ul.get(0); 730 if (u == null) { 731 return locationURL; 732 } 733 u = u.trim(); 734 if (u.length() == 0) { 735 return locationURL; 736 } 737 List pl = (List)map.get( 738 SAML2Constants.BASIC_AUTH_PASSWD); 739 String p = null; 740 if (pl != null && !pl.isEmpty()) { 741 p = (String) pl.get(0); 742 } 743 if (p == null) { 744 p = ""; 745 } 746 747 String dp = SAMLUtilsCommon.decodePassword(p); 748 749 int index = locationURL.indexOf("//"); 750 return locationURL.substring(0, index+2) + 751 u + ":" + dp + "@" + 752 locationURL.substring(index+2); 753 } 754 755 /** 756 * Converts a value of XML boolean type to Boolean object. 757 * 758 * @param str a value of XML boolean type 759 * @return a Boolean object. 760 * @throws SAML2Exception if there is a syntax error 761 */ 762 public static Boolean StringToBoolean(String str) throws SAML2Exception { 763 if (str == null) { 764 return null; 765 } 766 767 if (str.equals("true") || str.equals("1")) { 768 return Boolean.TRUE; 769 } 770 771 if (str.equals("false") || str.equals("0")) { 772 return Boolean.FALSE; 773 } 774 775 throw new SAML2Exception(SAML2SDKUtils.bundle.getString( 776 "invalidXMLBooleanValue")); 777 } 778 779 /** 780 * Removes deployment URI from the pass down string. i.e. 781 * from "/opensso/ArtifactResolver/metaAlias/idp" to 782 * "/ArtifactResolver/metaAlias/idp". 783 * @param uri the URI string which the deployment uri is to be removed 784 * return string without deployment uri 785 */ 786 public static String removeDeployUri(String uri) { 787 if ((uri == null) || (uri.length() == 0)) { 788 return uri; 789 } 790 int loc = uri.indexOf("/", 1); 791 if (loc == -1) { 792 return null; 793 } else { 794 return uri.substring(loc); 795 } 796 } 797 798 /** 799 * Returns the boolean value as a <code>Boolean</code> object. 800 * 801 * @param value boolean value true or false. 802 * 803 */ 804 public static Boolean booleanValueOf(String value) { 805 return new Boolean("true".equalsIgnoreCase(value) || "1".equals(value)); 806 } 807}
Copyright © 2010-2017, ForgeRock All Rights Reserved.