Package com.sun.xml.wss.core

Source Code of com.sun.xml.wss.core.UsernameToken

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010-2014 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*
* $Id: UsernameToken.java,v 1.2 2010-10-21 15:37:12 snajper Exp $
*/

package com.sun.xml.wss.core;


import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import org.apache.xml.security.exceptions.Base64DecodingException;
import com.sun.xml.wss.impl.misc.Base64;
import com.sun.xml.wss.logging.LogDomainConstants;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.impl.SecurityTokenException;
import com.sun.xml.wss.impl.XMLUtil;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.impl.misc.SecurityHeaderBlockImpl;

import com.sun.xml.ws.security.Token;

/*
<xsd:complexType name="UsernameTokenType">
- <xsd:annotation>
- <xsd:documentation>
This type represents a username token per Section 4.1
</xsd:documentation>
</xsd:annotation>
- <xsd:sequence>
<xsd:element name="Username" type="wsse:AttributedString"/>
<xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute ref="wsu:Id"/>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:complexType>
*/

/**
*
* Support for a WSS:Username Token Profile.
*
* Represents a wsse:UsernameToken.
*
* @author Manveen Kaur
* @author Edwin Goei
*/
public class UsernameToken extends SecurityHeaderBlockImpl
implements SecurityToken, Token {
   
    public static final long MAX_NONCE_AGE = 900000; //milliseconds

    private String username;
   
    private String password = null;
   
    // password type
    private String passwordType = MessageConstants.PASSWORD_TEXT_NS;
   
    // password Digest value
    private String passwordDigest = null;
   
    private byte[] decodedNonce = null;
   
    // specifies a cryptographically random sequence
    private String nonce = null;
   
    // default nonce encoding
    private String nonceEncodingType = MessageConstants.BASE64_ENCODING_NS;
   
    // time stamp to indicate creation time
    private String created = null;

    // flag to indicate whether BSP checks should be made or not.
    private boolean bsp = false;
   
    private Document soapDoc;
   
    private static Logger log =
    Logger.getLogger(
    LogDomainConstants.WSS_API_DOMAIN,
    LogDomainConstants.WSS_API_DOMAIN_BUNDLE);
   
    public static SecurityHeaderBlock fromSoapElement(SOAPElement element) throws XWSSecurityException {
        return SecurityHeaderBlockImpl.fromSoapElement(
        element, UsernameToken.class);
    }
   
    public UsernameToken(Document document, String username) throws SecurityTokenException {
        this.soapDoc = document;
        this.username = username;
        // set default password type       
        setPasswordType(MessageConstants.PASSWORD_TEXT_NS);
    }
   
    public UsernameToken( Document document,String username,String password,boolean digestPassword) throws SecurityTokenException {
        this(document, username);
        this.password = password;
        if (digestPassword) {
            setPasswordType(MessageConstants.PASSWORD_DIGEST_NS);
        }
    }
   
    public UsernameToken(Document document, String username, String password) throws SecurityTokenException {
        this(document, username, password, false);
    }
   
    /**
     * C'tor that creates the optional element nonce, created is not set.
     */
    public UsernameToken(Document document,String username, String password,  boolean setNonce, boolean digestPassword) throws SecurityTokenException {
       
        this(document, username, password, digestPassword);
        if (setNonce) {
            createNonce();
        }
    }
   
    /**
     * C'tor that creates the optional elements of nonce and created.
     */
    public UsernameToken(Document document,String username,String password,boolean setNonce,boolean setCreatedTimestamp,boolean digestPassword)
    throws SecurityTokenException {
   
        this(document, username, password, setNonce, digestPassword);
        if (setCreatedTimestamp) {
            try {
                this.created = getCreatedFromTimestamp();
            } catch (Exception e) {
                log.log(Level.SEVERE, "WSS0280.failed.create.UsernameToken", e);
                throw new SecurityTokenException(e);
            }
        }       
    }

    public UsernameToken(SOAPElement usernameTokenSoapElement, boolean bspFlag) throws XWSSecurityException {
        this(usernameTokenSoapElement);
        isBSP(bspFlag);
    }

    /**
     * Extracts info from SOAPElement representation
     *
     * @param usernameTokenSoapElement
     */
    public UsernameToken(SOAPElement usernameTokenSoapElement) throws XWSSecurityException {
       
        setSOAPElement(usernameTokenSoapElement);
        this.soapDoc = getOwnerDocument();
       
        if (!("UsernameToken".equals(getLocalName()) &&
        XMLUtil.inWsseNS(this))) {
            log.log(
            Level.SEVERE,
            "WSS0329.usernametoken.expected",
            new Object[] {getLocalName()});
           
            throw new SecurityTokenException(
            "Expected UsernameToken Element, but Found " + getLocalName());
        }
       
        boolean invalidToken = false;
       
        Iterator children = getChildElements();
       
        // Check that the first child element is a Username
       
        Node object = null;
        while (children.hasNext() && !(object instanceof SOAPElement)) {
            object = (Node)children.next();
        }

        if ((object != null) && (object.getNodeType() == Node.ELEMENT_NODE)) {
            SOAPElement element = (SOAPElement) object;
            if ("Username".equals(element.getLocalName()) &&
            XMLUtil.inWsseNS(element)) {
                username = element.getValue();
            } else {
                log.log(Level.SEVERE,"WSS0330.usernametoken.firstchild.mustbe.username");
                throw new SecurityTokenException("The first child of a UsernameToken Element, should be"
                + " a Username ");
            }
        } else {
            invalidToken = true;
        }
       
        while (children.hasNext()) {
           
            object = (Node)children.next();

            if (object.getNodeType() == Node.ELEMENT_NODE) {

                SOAPElement element = (SOAPElement) object;
                if ("Password".equals(element.getLocalName()) &&
                XMLUtil.inWsseNS(element)) {
                    String passwordType = element.getAttribute("Type");
                   
                    if (isBSP() && passwordType.length() < 1) {
                        // Type should be specified
                        log.log(Level.SEVERE,"BSP4201.PasswordType.Username");
                        throw new XWSSecurityException(" A wsse:UsernameToken/wsse:Password element in a SECURITY_HEADER MUST specify a Type attribute.");
                    }
                   
                    if (!"".equals(passwordType))                       
                        setPasswordType(passwordType);
                   
                    if (MessageConstants.PASSWORD_TEXT_NS == this.passwordType)
                        password = element.getValue();
                    else
                        passwordDigest = element.getValue();
                }
                else if ("Nonce".equals(element.getLocalName()) && XMLUtil.inWsseNS(element)) {
                    nonce = element.getValue();
                    String encodingType =
                    element.getAttribute("EncodingType");
                    if (!"".equals(encodingType))
                        setNonceEncodingType(encodingType);
                    try {
                        decodedNonce = Base64.decode(nonce);
                    } catch (Base64DecodingException bde) {
                        log.log(Level.SEVERE, "WSS0309.couldnot.decode.base64.nonce", bde);
                        throw new XWSSecurityException(bde);
                    }
                }
                else if ("Created".equals(element.getLocalName()) &&
                XMLUtil.inWsuNS(element)) {
                    created = element.getValue();
                } else {
                    invalidToken = true;
                }
            }
        }
       
        if (invalidToken) {
            log.log(Level.SEVERE, "WSS0331.invalid.usernametoken");
            throw new SecurityTokenException(
            "Element passed was not a SOAPElement or"
            + " is not a proper UsernameToken");
        }
       
        if (null == username) {
            log.log(Level.SEVERE, "WSS0332.usernametoken.null.username");
            throw new SecurityTokenException(
            "Username token does not contain the username");
        }
    }
   
    /**
     * @return Returns the username.
     */
    public String getUsername() {
        return username;
    }
   
    public void setUsername(String username) {
        this.username = username;
    }
   
    /**
     * @return Returns the password which may be null meaning no password.
     */
    public String getPassword() {
        return password;
    }
   
    /**
     * @return Returns the passwordType.
     */
    public String getPasswordType() {
        return passwordType;
    }
   
    private void setPasswordType(String passwordType)
    throws SecurityTokenException {
       
        if (MessageConstants.PASSWORD_TEXT_NS.equals(passwordType)) {
            this.passwordType = MessageConstants.PASSWORD_TEXT_NS;
        } else if (MessageConstants.PASSWORD_DIGEST_NS.equals(passwordType)) {
            this.passwordType =  MessageConstants.PASSWORD_DIGEST_NS;
        } else {
            log.log(Level.SEVERE, "WSS0306.invalid.passwd.type",
            new Object[] {
                MessageConstants.PASSWORD_TEXT_NS,
                MessageConstants.PASSWORD_DIGEST_NS});
                throw new SecurityTokenException(
                "Invalid password type. Must be one of   " +
                MessageConstants.PASSWORD_TEXT_NS + " or " +
                MessageConstants.PASSWORD_DIGEST_NS);
        }
    }
   
    /**
     * @return Returns the Nonce Encoding type.
     */
    public String getNonceEncodingType() {
        return this.nonceEncodingType;
    }
   
    /**
     * Sets the nonce encoding type.
     * As per WSS:UserNameToken profile, for valid values, refer to
     * wsse:BinarySecurityToken schema.
     */
    private void setNonceEncodingType(String nonceEncodingType) {
       
        if (!MessageConstants.BASE64_ENCODING_NS.equals(nonceEncodingType)) {
            log.log(Level.SEVERE,"WSS0307.nonce.enctype.invalid");
            throw new RuntimeException("Nonce encoding type invalid");
        }
        this.nonceEncodingType = MessageConstants.BASE64_ENCODING_NS;
    }
   
   
    /**
     * @return Returns the encoded nonce. Null indicates no nonce was set.
     */
    public String getNonce() throws SecurityTokenException {
        return nonce;
    }
   
    /**
     * Returns the created which may be null meaning no time of creation.
     */
    public String getCreated() {
        return created;
    }
   
    public String getPasswordDigest() {
        return this.passwordDigest;
    }
   
    /**
     * Sets the password.
     * @param passwd
     */   
    public void setPassword(String passwd){
        this.password = passwd;
    }
   
    /**
     * set the nonce value.If nonce value is null then it will create one.
     * @param nonceValue
     */   
    public void setNonce(String nonceValue){
        if(nonceValue == null || MessageConstants.EMPTY_STRING.equals(nonceValue)){
            createNonce();
        }else{
            this.nonce = nonceValue;
        }
    }
    /**
     * set the creation time.
     * @param time If null or empty then this method would create one.
     */   
    public void setCreationTime(String time) throws XWSSecurityException {
        if(time == null || MessageConstants.EMPTY_STRING.equals(time)){
            this.created = getCreatedFromTimestamp();
        }else{
            this.created = time;
        }
    }
   
    public void setDigestOn() throws SecurityTokenException {
        setPasswordType(MessageConstants.PASSWORD_DIGEST_NS);
    }
   
    public SOAPElement getAsSoapElement() throws SecurityTokenException {
       
        if (null != delegateElement)
            return delegateElement;
        try {
            setSOAPElement(
            (SOAPElement) soapDoc.createElementNS(
            MessageConstants.WSSE_NS,
            MessageConstants.WSSE_PREFIX + ":UsernameToken"));
           
            addNamespaceDeclaration(
            MessageConstants.WSSE_PREFIX,
            MessageConstants.WSSE_NS);
           
            if (null == username || MessageConstants._EMPTY.equals(username) ) {
                log.log(Level.SEVERE, "WSS0387.error.creating.usernametoken");
                throw new SecurityTokenException("username was not set");
            } else {
                addChildElement("Username", MessageConstants.WSSE_PREFIX)
                .addTextNode(username);
            }
           
            if (password != null && !MessageConstants._EMPTY.equals(password) ) {
                SOAPElement wssePassword =
                addChildElement("Password", MessageConstants.WSSE_PREFIX);
               
                if (MessageConstants.PASSWORD_DIGEST_NS == passwordType) {
                    createDigest();
                    wssePassword.addTextNode(passwordDigest);
                } else {
                    wssePassword.addTextNode(password);
                }
                wssePassword.setAttribute("Type", passwordType);
            }
           
            if (nonce != null) {
                SOAPElement wsseNonce =
                addChildElement("Nonce", MessageConstants.WSSE_PREFIX);
                wsseNonce.addTextNode(nonce);
               
                if (nonceEncodingType != null) {
                    wsseNonce.setAttribute("EncodingType", nonceEncodingType);
                }
            }
           
            if (created != null) {
                SOAPElement wsuCreated =
                addChildElement(
                "Created",
                MessageConstants.WSU_PREFIX,
                MessageConstants.WSU_NS);
                wsuCreated.addTextNode(created);
            }
           
        } catch (SOAPException se) {
            log.log(Level.SEVERE, "WSS0388.error.creating.usernametoken", se.getMessage());
            throw new SecurityTokenException(
            "There was an error creating Username Token " +
            se.getMessage());
        }
        return delegateElement;
    }
   
    /*
     * Create a unique nonce. Default encoded with base64.
     * A nonce is a random value that the sender creates
     * to include in the username token that it sends.
     * Nonce is an effective counter measure against replay attacks.
     */
    private void createNonce() {
       
        this.decodedNonce = new byte[18];
        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.nextBytes(decodedNonce);
        } catch (NoSuchAlgorithmException e) {
            log.log(Level.SEVERE, "WSS0310.no.such.algorithm",
            new Object[] {e.getMessage()});
            throw new RuntimeException(
            "No such algorithm found" + e.getMessage());
        }
        if (MessageConstants.BASE64_ENCODING_NS == nonceEncodingType)
            this.nonce = Base64.encode(decodedNonce);
        else {
            log.log(Level.SEVERE, "WSS0389.unrecognized.nonce.encoding", nonceEncodingType);
            throw new RuntimeException(
            "Unrecognized encoding: " + nonceEncodingType);
        }
    }
   
    /*
     * Password Digest creation.
     * As per WSS-UsernameToken spec, if either or both of <wsse:Nonce>
     * and <wsu:Created> are present, then they must be included in the
     * digest as follows:
     *
     * Password_digest = Base64( SHA_1 (nonce + created + password) )
     *
     */
    private void createDigest() throws SecurityTokenException {
       
        String utf8String = "";
        if (created != null) {
            utf8String = utf8String + created;
        }
       
        // password is also optional
        if (password != null) {
            utf8String = utf8String + password;
        }
       
        byte[] utf8Bytes;
        try {
            utf8Bytes = utf8String.getBytes("utf-8");
        } catch (UnsupportedEncodingException uee) {
            log.log(Level.SEVERE, "WSS0390.unsupported.charset.exception");
            throw new SecurityTokenException(uee);
        }
       
        byte[] bytesToHash;
        if (decodedNonce != null) {
            bytesToHash = new byte[utf8Bytes.length + 18];
            for (int i = 0; i < 18; i++)
                bytesToHash[i] = decodedNonce[i];
            for (int i = 18; i < utf8Bytes.length + 18; i++)
                bytesToHash[i] = utf8Bytes[i - 18];
        } else {
            bytesToHash = utf8Bytes;
        }
       
        byte[] hash;
        try {
            MessageDigest sha = MessageDigest.getInstance("SHA-1");
            hash = sha.digest(bytesToHash);
        } catch (Exception e) {
            log.log(Level.SEVERE, "WSS0311.passwd.digest.couldnot.be.created",
            new Object[] {e.getMessage()});
            throw new SecurityTokenException(
            "Password Digest could not be created. " + e.getMessage());
        }
        this.passwordDigest = Base64.encode(hash);
    }
   
    private String getCreatedFromTimestamp() throws XWSSecurityException {
        Timestamp ts = new Timestamp();
        ts.createDateTime();
        return ts.getCreated();
    }
   
    public void isBSP(boolean flag) {
        bsp = flag;
    }

    public boolean isBSP() {
        return bsp;
    }

    public String getType() {
        return MessageConstants.USERNAME_TOKEN_NS;
    }

    public Object getTokenValue() {
        log.log(Level.SEVERE, "WSS0281.unsupported.operation");
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
TOP

Related Classes of com.sun.xml.wss.core.UsernameToken

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.