/*******************************************************************************
 * Copyright (c) 2017 Synopsys, Inc
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Synopsys, Inc - initial implementation and documentation
 *******************************************************************************/
package jenkins.plugins.coverity.ws;

import com.sun.xml.wss.ProcessingContext;
import com.sun.xml.wss.XWSSProcessor;
import com.sun.xml.wss.XWSSProcessorFactory;
import com.sun.xml.wss.XWSSecurityException;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;

/**
 * SOAP handler for user authentication using ws-security.  This mechanism inserts the user's user name and password in
 * the SOAP header of each message.
 */
public class ClientAuthenticationHandlerWSS implements SOAPHandler<SOAPMessageContext> {
    public static final String WSS_AUTH_PREFIX = "wsse";
    public static final String WSS_AUTH_LNAME = "Security";
    public static final String WSS_AUTH_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    private XWSSProcessor xwssProcessor = null;

    private String quote(String in) {
        return in.replace("\"", "&quot;");
    }

    public ClientAuthenticationHandlerWSS(String userName, String password) {
        String xwssConfigText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> " +
                "<xwss:SecurityConfiguration xmlns:xwss=\"http://java.sun.com/xml/ns/xwss/config\"> " +
                "<xwss:UsernameToken name=\"" + quote(userName) + "\" " +
                "password=\"" + quote(password) + "\" " +
                "useNonce=\"false\" digestPassword=\"false\"/>  " +
                "</xwss:SecurityConfiguration>";
        InputStream xwssConfig = new ByteArrayInputStream(xwssConfigText.getBytes(StandardCharsets.UTF_8));
        ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
            XWSSProcessorFactory factory = XWSSProcessorFactory.newInstance();
            xwssProcessor = factory.createProcessorForSecurityConfiguration(xwssConfig, new SecurityEnvironmentHandler());
        } catch(XWSSecurityException se) {
            throw new RuntimeException(se);
        } finally {
            Thread.currentThread().setContextClassLoader(oldCCL);
        }
    }

    @PostConstruct
    public void init() {
    }

    @PreDestroy
    public void destroy() {
    }

    public boolean handleFault(SOAPMessageContext mc) {
        return true;
    }

    public void close(MessageContext mc) {
    }

    public Set<QName> getHeaders() {
        QName securityHeader = new QName(WSS_AUTH_URI, WSS_AUTH_LNAME, WSS_AUTH_PREFIX);
        HashSet<QName> headers = new HashSet<QName>();
        headers.add(securityHeader);
        return headers;
    }

    public boolean handleMessage(SOAPMessageContext smc) {
        boolean outbound = ((Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();
        SOAPMessage msg = smc.getMessage();
        if(outbound) {
            try {
                ProcessingContext context = xwssProcessor.createProcessingContext(msg);
                context.setSOAPMessage(msg);
                SOAPMessage secureMsg = xwssProcessor.secureOutboundMessage(context);
                smc.setMessage(secureMsg);
            } catch(XWSSecurityException ex) {
                throw new RuntimeException(ex);
            } catch(Exception e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }

    private static class SecurityEnvironmentHandler implements CallbackHandler {

        public void handle(Callback[] callbacks) throws UnsupportedCallbackException {

        }
    }


}

@@ -1338,16 +1338,67 @@
 l.Set;%0A%0A
+import org.apache.commons.lang.StringEscapeUtils;%0A%0A
 /**%0A * S
@@ -1943,96 +1943,8 @@
 l;%0A%0A
-    private String quote(String in) %7B%0A        return in.replace(%22%5C%22%22, %22&quot;%22);%0A    %7D%0A%0A
     
@@ -2249,21 +2249,43 @@
 e=%5C%22%22 + 
-quote
+StringEscapeUtils.escapeXml
 (userNam
@@ -2333,13 +2333,35 @@
 %22 + 
-quote
+StringEscapeUtils.escapeXml
 (pas

Update web service authentication handler to escapeXml for username / password