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: BinarySecurityToken.java,v 1.5 2008/08/06 17:28:07 exu Exp $ 026 * 027 */ 028 029 030package com.sun.identity.liberty.ws.common.wsse; 031 032import com.sun.identity.shared.debug.Debug; 033import com.sun.identity.shared.xml.XMLUtils; 034import com.sun.identity.saml.common.SAMLUtils; 035import java.util.ResourceBundle; 036import java.util.Map; 037import java.util.HashMap; 038import com.sun.identity.shared.locale.Locale; 039import org.w3c.dom.Document; 040import org.w3c.dom.Element; 041import org.w3c.dom.NamedNodeMap; 042import org.w3c.dom.Attr; 043import javax.xml.namespace.QName; 044import com.sun.identity.liberty.ws.soapbinding.SOAPBindingConstants; 045import com.sun.identity.liberty.ws.soapbinding.Utils; 046 047/** 048 * The class <code>BinarySecurityToken</code> provides interface to parse and 049 * create X.509 Security Token depicted by Web Service Security : X.509 050 * Certificate Token Profile and Liberty ID-WSF Security Mechanisms 051 * specifications. 052 * <p>The following schema fragment specifies the expected content within the BinarySecurityToken object. 053 * <p> 054 * <pre> 055 * <element name="BinarySecurityToken" type="wsse:BinarySecurityTokenType/> 056 * <complexType name="BinarySecurityTokenType"> 057 * <simpleContent> 058 * <extension base="<http://schemas.xmlsoap.org/ws/2003/06/secext>EncodedString"> 059 * <attribute name="ValueType" type="{http://www.w3.org/2001/XMLSchema}QName" /> 060 * </extension> 061 * </simpleContent> 062 * </complexType> 063 * <xsd:complexType name="EncodedString"> 064 * <xsd:simpleContent> 065 * <xsd:extension base="wsse:AttributedString"> 066 * <xsd:attribute name="EncodingType" type="xsd:QName"/> 067 * </xsd:extension> 068 * </xsd:simpleContent> 069 * </xsd:complexType> 070 * <xsd:complexType name="AttributedString"> 071 * <xsd:simpleContent> 072 * <xsd:extension base="xsd:string"> 073 * <xsd:attribute ref="wsu:Id"/> 074 * <xsd:anyAttribute namespace="##other" processContents="lax"/> 075 * </xsd:extension> 076 * </xsd:simpleContent> 077 * </xsd:complexType> 078 * </pre> 079 * 080 * @supported.api 081 */ 082public class BinarySecurityToken { 083 084 private String value = null; 085 private QName valueType = null; 086 private QName encodingType = null; 087 private String id = null; 088 private String xmlString = null; 089 private static ResourceBundle bundle = Locale.getInstallResourceBundle( 090 "libBinarySecurityToken"); 091 private static Debug debug = Debug.getInstance("libIDWSF"); 092 093 private static final String WSSE = "wsse"; 094 private static final String WSU = "wsu"; 095 private static final String BINARY_SECURITY_TOKEN = "BinarySecurityToken"; 096 private static final String ENCODING_TYPE = "EncodingType"; 097 private static final String VALUE_TYPE = "ValueType"; 098 private static final String ID = "Id"; 099 private static final String XML_NS = "xmlns"; 100 101 private String wsfVersion = null; 102 private String wsseNS = null; 103 private String wsuNS = null; 104 105 /** 106 * Default constructor 107 */ 108 private BinarySecurityToken () {} 109 110 /** 111 * Constructor. 112 * @param value the value must be the specified <code>valueType</code> 113 * and encoded in the specified <code>encodingType</code>. 114 * 115 * @param valueType type of the value 116 * @param encodingType encoding type of the value 117 * @exception Exception if any input parameter is null 118 * @supported.api 119 */ 120 public BinarySecurityToken (String value, 121 QName valueType, 122 QName encodingType) 123 throws Exception 124 { 125 if (value == null || valueType == null || encodingType == null) { 126 debug.error("BinarySecurityToken: null input param"); 127 throw new Exception(bundle.getString("nullInputParameter")) ; 128 } 129 this.value = value; 130 this.valueType = valueType; 131 this.encodingType = encodingType; 132 this.id = SAMLUtils.generateID(); 133 setWSFVersion(Utils.getDefaultWSFVersion()); 134 } 135 136 /** 137 * Constructor. 138 * @param token Binary Security Token Element 139 * @exception Exception if token Element is not a valid binary 140 * security token 141 * @supported.api 142 */ 143 public BinarySecurityToken(Element token) 144 throws Exception { 145 if (token == null) { 146 debug.error("BinarySecurityToken: null input token"); 147 throw new Exception(bundle.getString("nullInputParameter")) ; 148 } 149 150 // check element name 151 String elementName = token.getLocalName(); 152 if (elementName == null) { 153 debug.error("BinarySecurityToken: local name missing"); 154 throw new Exception(bundle.getString("nullInput")) ; 155 } 156 if (!(elementName.equals(BINARY_SECURITY_TOKEN))) { 157 debug.error("BinarySecurityToken: invalid root element"); 158 throw new Exception(bundle.getString("invalidElement") + 159 ":" + elementName) ; 160 } 161 162 wsseNS = token.getNamespaceURI(); 163 if ((wsseNS != null) && WSSEConstants.NS_WSSE_WSF11.equals(wsseNS)) { 164 wsfVersion = SOAPBindingConstants.WSF_11_VERSION; 165 } else if((wsseNS != null) && WSSEConstants.NS_WSSE.equals(wsseNS)) { 166 wsfVersion = SOAPBindingConstants.WSF_10_VERSION; 167 } else { 168 throw new Exception(bundle.getString("invalidNameSpace")); 169 } 170 171 // check attributes 172 NamedNodeMap nm = token.getAttributes(); 173 if (nm == null) { 174 debug.error("BinarySecurityToken: missing attr in element"); 175 throw new Exception(bundle.getString("missingAttribute")); 176 } 177 int len = nm.getLength(); 178 for (int i = 0; i < len; i++) { 179 Attr attr = (Attr) nm.item(i); 180 String localName = attr.getLocalName(); 181 if (localName == null) { 182 // exception?? Ignore for now 183 if (debug.messageEnabled()) { 184 debug.message("BST.Elemement, invalid attr " + localName); 185 } 186 continue; 187 } 188 // check Id/EncodingType/ValueType attribute 189 if (localName.equals(ID)) { 190 this.id = attr.getValue(); 191 wsuNS = attr.getNamespaceURI(); 192 } else if (localName.equals(ENCODING_TYPE)) { 193 // no namespace match done here 194 encodingType = (QName) 195 encodingMap.get(trimPrefix(attr.getValue())); 196 } else if (localName.equals(VALUE_TYPE)) { 197 // no namespace match done here 198 valueType = (QName) valueMap.get(trimPrefix(attr.getValue())); 199 } 200 } 201 202 if (id == null || id.length() == 0) { 203 debug.error("BinarySecurityToken: ID missing"); 204 throw new Exception(bundle.getString("missingAttribute") + 205 " : " + ID); 206 } 207 208 if (encodingType == null) { 209 debug.error("BinarySecurityToken: encoding type missing"); 210 throw new Exception(bundle.getString("missingAttribute") + 211 " : " + ENCODING_TYPE); 212 } 213 214 if (valueType == null) { 215 debug.error("BinarySecurityToken: valueType missing"); 216 throw new Exception(bundle.getString("missingAttribute") + 217 " : " + VALUE_TYPE); 218 } 219 220 // get X509 certificate value 221 try { 222 this.value = token.getFirstChild().getNodeValue().trim(); 223 } catch (Exception e) { 224 debug.error("BinarySecurityToken: unable to get value", e); 225 this.value = null; 226 } 227 228 if (value == null) { 229 debug.error("BinarySecurityToken: value missing"); 230 throw new Exception(bundle.getString("missingValue")); 231 } 232 233 // save the original string for toString() 234 xmlString = XMLUtils.print(token); 235 236 } 237 238 /** 239 * trim prefix and get the value, e.g, for wsse:X509v3 will return X509v3 240 */ 241 private String trimPrefix(String val) { 242 if ((val != null) && 243 (val.startsWith(WSSEConstants.NS_X509) || 244 val.startsWith(WSSEConstants.NS_SMS))) { 245 return val; 246 } 247 248 int pos = val.indexOf(":"); 249 if (pos == -1) { 250 return val; 251 } else if (pos == val.length()) { 252 return ""; 253 } else { 254 return val.substring(pos+1); 255 } 256 } 257 258 /** 259 * Gets encoding type for the token. 260 * 261 * @return encoding type for the token. 262 * @supported.api 263 */ 264 public QName getEncodingType() { 265 return encodingType; 266 } 267 268 /** 269 * Gets value type for the token. 270 * 271 * @return value type for the token. 272 * @supported.api 273 */ 274 public QName getValueType() { 275 return valueType; 276 } 277 278 /** 279 * Gets id attribute for the tokens. 280 * 281 * @return id attribute for the token. 282 * @supported.api 283 */ 284 public String getId() { 285 return id; 286 } 287 288 /** 289 * Gets value of the token. 290 * 291 * @return value of the token. 292 * @supported.api 293 */ 294 public String getTokenValue() { 295 return value; 296 } 297 298 /** 299 * Returns a String representation of the token. 300 * @return A string containing the valid XML for this element 301 * @supported.api 302 */ 303 public String toString() { 304 if (xmlString == null) { 305 StringBuffer sb = new StringBuffer(); 306 307 sb.append("<").append(WSSE).append(":") 308 .append(BINARY_SECURITY_TOKEN).append(" ").append(XML_NS) 309 .append(":").append(WSSE).append("=\"").append(wsseNS) 310 .append("\" ").append(XML_NS).append(":").append(WSU) 311 .append("=\"").append(wsuNS).append("\" ").append(WSU) 312 .append(":").append(ID).append("=\"").append(id).append("\" ") 313 .append(VALUE_TYPE).append("=\""); 314 if (SOAPBindingConstants.WSF_11_VERSION.equals(wsfVersion)) { 315 sb.append(WSSEConstants.NS_X509).append("#") 316 .append(valueType.getLocalPart()).append("\" ") 317 .append(ENCODING_TYPE).append("=\"") 318 .append(WSSEConstants.NS_SMS).append("#") 319 .append(encodingType.getLocalPart()).append("\">\n"); 320 } else { 321 sb.append(WSSE).append(":").append(valueType.getLocalPart()) 322 .append("\" ").append(ENCODING_TYPE).append("=\"") 323 .append(WSSE).append(":") 324 .append(encodingType.getLocalPart()).append("\">\n"); 325 } 326 sb.append(value.toString()).append("\n").append("</").append(WSSE) 327 .append(":").append(BINARY_SECURITY_TOKEN).append(">\n"); 328 xmlString = sb.toString(); 329 } 330 return xmlString; 331 } 332 333 /** 334 * The <code>X509V3</code> value type indicates that 335 * the value name given corresponds to a X509 Certificate. 336 * @supported.api 337 */ 338 public static final QName X509V3 = new QName("X509v3"); 339 340 /** 341 * The <code>KERBEROSV5TGT</code> value type indicates that 342 * the value name given corresponds to a Kerberos V5 TGT. 343 */ 344 public static final QName KERBEROSV5TGT = new QName("Kerberosv5TGT"); 345 346 /** 347 * The <code>KERBEROSV5ST</code> value type indicates 348 * that the value name given corresponds to a Kerberos V5 service ticket. 349 */ 350 public static final QName KERBEROSV5ST = new QName("Kerberosv5ST"); 351 352 /** 353 * The <code>PKCS7</code> value type indicates 354 * that the value name given corresponds to a 355 * PKCS7 object. 356 * @supported.api 357 */ 358 public static final QName PKCS7 = new QName("PKCS7"); 359 360 /** 361 * The <code>PKIPATH</code> value type indicates 362 * that the value name given corresponds to a 363 * PKI Path object. 364 * @supported.api 365 */ 366 public static final QName PKIPath = new QName("PKIPath"); 367 368 // map from string to ValueType object 369 static Map valueMap = new HashMap(); 370 static { 371 valueMap.put(X509V3.getLocalPart(), X509V3); 372 valueMap.put(PKIPath.getLocalPart(), PKIPath); 373 valueMap.put(PKCS7.getLocalPart(), PKCS7); 374 valueMap.put(KERBEROSV5ST.getLocalPart(), KERBEROSV5ST); 375 valueMap.put(KERBEROSV5TGT.getLocalPart(), KERBEROSV5TGT); 376 valueMap.put(WSSEConstants.NS_X509 + "#X509v3", X509V3); 377 } 378 379 /** 380 * The <code>BASE64BINARY</code> encoding type indicates that the encoding 381 * name given corresponds to base64 encoding of a binary value. 382 * @supported.api 383 */ 384 public static final QName BASE64BINARY = new QName("Base64Binary"); 385 386 /** 387 * The <code>HEXBINARY</code> encoding type indicates that 388 * the encoding name given corresponds to Hex encoding of 389 * a binary value. 390 * @supported.api 391 */ 392 public static final QName HEXBINARY = new QName("HexBinary"); 393 394 // map from string to EncodingType object 395 static Map encodingMap = new HashMap(); 396 static { 397 encodingMap.put(HEXBINARY.getLocalPart(), HEXBINARY); 398 encodingMap.put(BASE64BINARY.getLocalPart(), BASE64BINARY); 399 encodingMap.put(WSSEConstants.NS_SMS + "#Base64Binary", BASE64BINARY); 400 } 401 402 /** 403 * Adds th binary security token to the header element. 404 * @param headerE the security header element. 405 * @exception Exception if there is a failure in adding to the header. 406 */ 407 public void addToParent(Element headerE) throws Exception { 408 409 Document doc = headerE.getOwnerDocument(); 410 Element securityE = doc.createElementNS(wsseNS, 411 WSSEConstants.TAG_WSSE + ":" + 412 WSSEConstants.TAG_SECURITYT); 413 securityE.setAttributeNS(SOAPBindingConstants.NS_XML, 414 WSSEConstants.TAG_XML_WSSE, wsseNS); 415 headerE.appendChild(securityE); 416 417 Document binaryTokenD = XMLUtils.toDOMDocument(toString(), debug); 418 419 Element binaryTokenE = binaryTokenD.getDocumentElement(); 420 securityE.appendChild(doc.importNode(binaryTokenE, true)); 421 422 } 423 424 /** 425 * Returns the web services version. 426 * @return the web services version. 427 */ 428 public String getWSFVersion() { 429 return wsfVersion; 430 } 431 432 /** 433 * Sets the web services version. 434 * @param version the web services version. 435 */ 436 public void setWSFVersion(String version) { 437 this.wsfVersion = version; 438 if(wsfVersion != null && 439 SOAPBindingConstants.WSF_10_VERSION.equals(wsfVersion)) { 440 wsseNS = WSSEConstants.NS_WSSE; 441 wsuNS = WSSEConstants.NS_WSU; 442 } else { 443 wsseNS = WSSEConstants.NS_WSSE_WSF11; 444 wsuNS = WSSEConstants.NS_WSU_WSF11; 445 } 446 xmlString = null; 447 } 448 449}