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 * &lt;element name="BinarySecurityToken" type="wsse:BinarySecurityTokenType/>
056 * &lt;complexType name="BinarySecurityTokenType">
057 *   &lt;simpleContent>
058 *     &lt;extension base="&lt;http://schemas.xmlsoap.org/ws/2003/06/secext>EncodedString">
059 *       &lt;attribute name="ValueType" type="{http://www.w3.org/2001/XMLSchema}QName" />
060 *     &lt;/extension>
061 *   &lt;/simpleContent>
062 * &lt;/complexType>
063 * &lt;xsd:complexType name="EncodedString">
064 *   &lt;xsd:simpleContent>
065 *     &lt;xsd:extension base="wsse:AttributedString">
066 *       &lt;xsd:attribute name="EncodingType" type="xsd:QName"/>
067 *     &lt;/xsd:extension>
068 *   &lt;/xsd:simpleContent>
069 * &lt;/xsd:complexType>
070 * &lt;xsd:complexType name="AttributedString">
071 *   &lt;xsd:simpleContent>
072 *     &lt;xsd:extension base="xsd:string">
073 *       &lt;xsd:attribute ref="wsu:Id"/>
074 *         &lt;xsd:anyAttribute namespace="##other" processContents="lax"/>
075 *     &lt;/xsd:extension>
076 *   &lt;/xsd:simpleContent>
077 * &lt;/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}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.