it.cnr.icar.eric.common.security.wss4j.WSS4JSecurityUtilBase.java Source code

Java tutorial

Introduction

Here is the source code for it.cnr.icar.eric.common.security.wss4j.WSS4JSecurityUtilBase.java

Source

/*
 * ====================================================================
 * This file is part of the ebXML Registry by Icar Cnr v3.2 
 * ("eRICv32" in the following disclaimer).
 *
 * "eRICv32" is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * "eRICv32" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License Version 3
 * along with "eRICv32".  If not, see <http://www.gnu.org/licenses/>.
 *
 * eRICv32 is a forked, derivative work, based on:
 *    - freebXML Registry, a royalty-free, open source implementation of the ebXML Registry standard,
 *      which was published under the "freebxml License, Version 1.1";
 *   - ebXML OMAR v3.2 Edition, published under the GNU GPL v3 by S. Krushe & P. Arwanitis.
 * 
 * All derivative software changes and additions are made under
 *
 * Copyright (C) 2013 Ing. Antonio Messina <messina@pa.icar.cnr.it>
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the freebxml Software Foundation.  For more
 * information on the freebxml Software Foundation, please see
 * "http://www.freebxml.org/".
 *
 * This product includes software developed by the Apache Software
 * Foundation (http://www.apache.org/).
 *
 * ====================================================================
 */
package it.cnr.icar.eric.common.security.wss4j;

import it.cnr.icar.eric.common.CanonicalConstants;
import it.cnr.icar.eric.common.CommonProperties;
import it.cnr.icar.eric.common.CommonResourceBundle;
import it.cnr.icar.eric.common.CredentialInfo;
import it.cnr.icar.eric.common.SOAPMessenger;

import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.xml.registry.RegistryException;
import javax.xml.soap.SOAPEnvelope;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecTimestamp;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;

public class WSS4JSecurityUtilBase {

    /** Key for configuration property 'max clock skew', passed to wss4j-security API.
     *  "The assumed maximum skew (milliseconds) between the local times of any two systems."
     */
    private static String getKeyMaxClockSkew() {
        return CommonProperties.getInstance().getProperty("eric.common.security.maxClockSkew");
    }

    private static Log log = LogFactory.getLog(SOAPMessenger.class);

    /**
     * Convenience method to extract an UUID/URN from a Content ID (CID). CIDs
     * are used for identifying attachments in signed SOAP messages.
     * 
     * @param cid
     *            The attachment's Content-ID.
     * @return The corresponding UUID/URN.
     */
    public static String convertContentIdToUUID(String cid) throws RegistryException {
        if (!(cid.charAt(0) == '<' && cid.charAt(cid.length() - 1) == '>')) {
            // error, not a cid URI Scheme id.
            throw new RegistryException(
                    CommonResourceBundle.getInstance().getString("message.CIDURIExpected", new Object[] { cid }));
        }

        String uuid = cid.substring(1, cid.length() - 1);
        return uuid;
    }

    /**
     * Convenience method to turn an UUID/URN into a Content ID (CID). CIDs are
     * used for identifying attachments in signed SOAP messages.
     * 
     * @param uuid
     *            The original UUID/URN.
     * @return The generated CID to be set as attachment Content-ID.
     */
    public static String convertUUIDToContentId(String uuid) {
        String cid = "<" + uuid + ">";
        return cid;
    }

    protected static List<WSEncryptionPart> createReferences(String soapNamespace) {
        List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
        WSEncryptionPart encP1 = new WSEncryptionPart(WSConstants.TIMESTAMP_TOKEN_LN, WSConstants.WSU_NS,
                "Element");
        parts.add(encP1);
        WSEncryptionPart encP2 = new WSEncryptionPart(WSConstants.ELEM_BODY, soapNamespace, "Content");
        parts.add(encP2);
        return parts;
    }

    protected static WSSecTimestamp createTimestamp() {

        WSSecTimestamp timestamp = new WSSecTimestamp();

        int timeToLive = 300; // default
        String maxClockSkew = getKeyMaxClockSkew();

        if (maxClockSkew != null) {
            try {
                timeToLive = Integer.parseInt(maxClockSkew);
            } catch (NumberFormatException e) {
                log.warn(CommonResourceBundle.getInstance().getString("message.InvalidlongValueForProperty",
                        new Object[] { maxClockSkew }), e);
            }
        }

        timestamp.setTimeToLive(timeToLive);
        return timestamp;
    }

    /*
     * Client has role SOAP receiver <-- signSOAPEnvelopeOnServerBST()
     */
    public static void verifySOAPEnvelopeOnClientBST(SOAPEnvelope se, CredentialInfo credentialInfo) {
        // remark: this method is not used since OMAR v3.0
        // client side verification of signatures is not implemented  
        try {
            Crypto crypto = CryptoFactory.getInstance("crypto-client.properties");
            verifySOAPEnvelopeBST(se, credentialInfo, crypto);
        } catch (WSSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } // default crypto

    }

    /*
     * Server has role SOAP receiver <-- signSOAPEnvelopeOnClientBST()
     * 
     *       certificate branch: RegistryBSTServlet
     */
    public static void verifySOAPEnvelopeOnServerBST(SOAPEnvelope se, CredentialInfo credentialInfo) {
        try {
            Crypto crypto = CryptoFactory.getInstance("crypto-server.properties");
            verifySOAPEnvelopeBST(se, credentialInfo, crypto);
        } catch (WSSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } // default crypto

    }

    protected static void verifySOAPEnvelopeBST(SOAPEnvelope se, CredentialInfo credentialInfo, Crypto crypto)
            throws WSSecurityException {

        WSSecurityEngine secEngine = new WSSecurityEngine();

        WSSConfig.init();

        Document doc = se.getOwnerDocument();

        List<WSSecurityEngineResult> results = secEngine.processSecurityHeader(doc, null, null, crypto);

        if (results != null) {

            WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
            X509Certificate cert = (X509Certificate) actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);

            // inject certificate for further processing
            credentialInfo.cert = cert;
        }
    }

    /*
     * Server has role SOAP sender --> verifySOAPEnvelopeOnClientBST()
     */
    public static void signSOAPEnvelopeOnServerBST(SOAPEnvelope se, CredentialInfo credentialInfo) {
        try {
            signSOAPEnvelopeBST(se, credentialInfo, CryptoFactory.getInstance("crypto-server.properties"));
        } catch (WSSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /*
     * Signing SOAP message with certificate
     */
    protected static void signSOAPEnvelopeBST(SOAPEnvelope se, CredentialInfo credentialInfo, Crypto userCrypto)
            throws WSSecurityException {

        WSSConfig.init();

        // inject empty SecHeader into Document
        Document doc = se.getOwnerDocument();
        WSSecHeader secHeader = new WSSecHeader();
        secHeader.insertSecurityHeader(doc);

        WSSecTimestamp timestamp = createTimestamp();
        timestamp.build(doc, secHeader);

        // overridden WSS4J path for explicit setPrivateKey()
        // <ds:Signature>
        WSS4JSignatureBST sign = new WSS4JSignatureBST();

        // <wsse:BinarySecurityToken ...>
        sign.setX509Certificate(credentialInfo.cert);
        sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);

        sign.setPrivateKey(credentialInfo.privateKey);

        // <ds:KeyInfo>
        sign.setCertUri(CanonicalConstants.CANONICAL_URI_SENDER_CERT);

        String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());

        // signature references
        // <ds:Reference>
        List<WSEncryptionPart> parts = createReferences(soapNamespace);
        sign.setParts(parts);

        sign.build(doc, userCrypto, secHeader);
    }

}