Package org.owasp.webscarab.plugin.openid

Source Code of org.owasp.webscarab.plugin.openid.OpenIdHTTPClient

/***********************************************************************
*
* This file is part of WebScarab, an Open Web Application Security
* Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2011 FedICT
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*/
package org.owasp.webscarab.plugin.openid;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bouncycastle.util.encoders.Base64;
import org.owasp.webscarab.httpclient.HTTPClient;
import org.owasp.webscarab.model.HttpUrl;
import org.owasp.webscarab.model.NamedValue;
import org.owasp.webscarab.model.Request;
import org.owasp.webscarab.model.Response;
import org.owasp.webscarab.util.Encoding;

/**
*
* @author Frank Cornelis
*/
public class OpenIdHTTPClient implements HTTPClient {

    private final HTTPClient httpClient;
    private final OpenIdProxyConfig openIdProxyConfig;

    public OpenIdHTTPClient(HTTPClient httpClient, OpenIdProxyConfig openIdProxyConfig) {
        this.httpClient = httpClient;
        this.openIdProxyConfig = openIdProxyConfig;
    }

    @Override
    public Response fetchResponse(Request request) throws IOException {
        if (false == this.openIdProxyConfig.doSomething()) {
            Response response = this.httpClient.fetchResponse(request);
            return response;
        }

        String openIdProxyHeader = "";

        if (this.openIdProxyConfig.doCorruptSignature()) {
            openIdProxyHeader += corruptSignature(request);
        }
        if (this.openIdProxyConfig.doRemoveSignature()) {
            openIdProxyHeader += removeSignature(request);
        }
        if (this.openIdProxyConfig.doRemoveRequestedAttribute()) {
            openIdProxyHeader += removeRequestedAttribute(request);
        }
        if (this.openIdProxyConfig.doAppendAttribute()) {
            openIdProxyHeader += appendAttribute(request);
        }
        if (this.openIdProxyConfig.doRemoveRequestAssociationHandle()) {
            openIdProxyHeader += removeRequestAssociationHandle(request);
        }
        if (this.openIdProxyConfig.doRemoveResponseAssociationHandle()) {
            openIdProxyHeader += removeResponseAssociationHandle(request);
        }

        if (false == openIdProxyHeader.isEmpty()) {
            request.addHeader("X-OpenIDProxy", openIdProxyHeader);
        }

        Response response = this.httpClient.fetchResponse(request);
        return response;
    }

    private NamedValue[] getParameters(Request request) {
        String method = request.getMethod();
        if ("GET".equals(method)) {
            HttpUrl httpUrl = request.getURL();
            String query = httpUrl.getQuery();
            if (null == query) {
                return null;
            }
            NamedValue[] values = NamedValue.splitNamedValues(query, "&", "=");
            return values;
        } else if ("POST".equals(method)) {
            byte[] requestContent = request.getContent();
            if (null == requestContent) {
                return null;
            }
            if (0 == requestContent.length) {
                return null;
            }
            String body = new String(requestContent);
            NamedValue[] values = NamedValue.splitNamedValues(
                    body, "&", "=");
            return values;
        } else {
            return null;
        }
    }

    private String removeSignature(Request request) {
        NamedValue[] values = getParameters(request);
        if (null == values) {
            return "";
        }
        boolean removedSignature = false;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            if ("openid.sig".equals(name)) {
                values[i] = null;
                removedSignature = true;
            }
            if ("openid.signed".equals(name)) {
                values[i] = null;
                removedSignature = true;
            }
        }
        if (false == removedSignature) {
            return "";
        }
        updateParameters(values, request);
        return "remove signature;";
    }
   
    private void updateParameters(NamedValue[] values, Request request) {
        updateParameters(values, null, request);
    }

    private void updateParameters(NamedValue[] values, List additionalParameters, Request request) {
        String method = request.getMethod();
        if ("GET".equals(method)) {
            try {
                HttpUrl httpUrl = request.getURL();
                setNewUrl(httpUrl, values, additionalParameters, request);
            } catch (MalformedURLException ex) {
                Logger.getLogger(OpenIdHTTPClient.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            // POST
            updateRequestPostParameters(values, additionalParameters, request);
        }
    }

    private String corruptSignature(Request request) {
        NamedValue[] values = getParameters(request);
        if (null == values) {
            return "";
        }
        boolean corruptedSignature = false;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if ("openid.sig".equals(name)) {
                byte[] decodedSignature = Base64.decode(value);
                decodedSignature[0]++;
                String corruptEncodedSignature = new String(Base64.encode(decodedSignature));
                values[i] = new NamedValue(name, corruptEncodedSignature);
                corruptedSignature = true;
                break;
            }
        }
        if (false == corruptedSignature) {
            return "";
        }
        updateParameters(values, request);
        return "corrupt signature;";
    }

    private void updateRequestPostParameters(NamedValue[] values, List additionalParameters, Request request) {
        StringBuilder stringBuffer = new StringBuilder();
        for (int i = 0; i < values.length; i++) {
            if (null == values[i]) {
                continue;
            }
            if (stringBuffer.length() > 1) {
                stringBuffer.append("&");
            }
            stringBuffer.append(values[i].getName());
            stringBuffer.append("=");
            stringBuffer.append(values[i].getValue());
        }
        if (null != additionalParameters) {
            Iterator additionalAttributesIter = additionalParameters.iterator();
            while (additionalAttributesIter.hasNext()) {
                NamedValue namedValue = (NamedValue) additionalAttributesIter.next();
                if (stringBuffer.length() > 1) {
                    stringBuffer.append("&");
                }
                stringBuffer.append(namedValue.getName());
                stringBuffer.append("=");
                stringBuffer.append(namedValue.getValue());
            }
        }
        byte[] content = stringBuffer.toString().getBytes();
        request.setContent(content);
    }

    private void setNewUrl(HttpUrl httpUrl, NamedValue[] values, Request request) throws MalformedURLException {
        setNewUrl(httpUrl, values, null, request);
    }

    private void setNewUrl(HttpUrl httpUrl, NamedValue[] values, List additionalAttributes, Request request) throws MalformedURLException {
        StringBuilder stringBuffer = new StringBuilder("?");
        for (int i = 0; i < values.length; i++) {
            if (null == values[i]) {
                continue;
            }
            if (stringBuffer.length() > 1) {
                stringBuffer.append("&");
            }
            stringBuffer.append(values[i].getName());
            stringBuffer.append("=");
            stringBuffer.append(values[i].getValue());
        }
        if (null != additionalAttributes) {
            Iterator additionalAttributesIter = additionalAttributes.iterator();
            while (additionalAttributesIter.hasNext()) {
                NamedValue namedValue = (NamedValue) additionalAttributesIter.next();
                stringBuffer.append("&");
                stringBuffer.append(namedValue.getName());
                stringBuffer.append("=");
                stringBuffer.append(namedValue.getValue());
            }
        }
        request.setURL(new HttpUrl(httpUrl.getSHPP() + stringBuffer.toString()));
    }

    private String removeRequestAssociationHandle(Request request) {
        NamedValue[] values = getParameters(request);
        if (null == values) {
            return "";
        }
        // check if OpenID request
        boolean openIdRequest = false;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if ("openid.mode".equals(name)) {
                if ("checkid_setup".equals(value)) {
                    openIdRequest = true;
                }
                break;
            }
        }
        if (false == openIdRequest) {
            return "";
        }
        // remove assoc_handle
        boolean assocHandleRemoved = false;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            if ("openid.assoc_handle".equals(name)) {
                values[i] = null;
                assocHandleRemoved = true;
                break;
            }
        }
        if (false == assocHandleRemoved) {
            return "";
        }
        // construct altered response
        updateParameters(values, request);
        return "removed request assoc_handle;";
    }

    private String removeResponseAssociationHandle(Request request) {
        NamedValue[] values = getParameters(request);
        if (null == values) {
            return "";
        }
        // check if OpenID response
        boolean openIdResponse = false;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if ("openid.mode".equals(name)) {
                if ("id_res".equals(value)) {
                    openIdResponse = true;
                }
                break;
            }
        }
        if (false == openIdResponse) {
            return "";
        }
        // remove assoc_handle
        boolean assocHandleRemoved = false;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            if ("openid.assoc_handle".equals(name)) {
                values[i] = null;
                assocHandleRemoved = true;
                break;
            }
        }
        if (false == assocHandleRemoved) {
            return "";
        }
        // construct altered response
        updateParameters(values, request);
        return "removed response assoc_handle;";
    }

    private String removeRequestedAttribute(Request request) {
        NamedValue[] values = getParameters(request);
        if (null == values) {
            return "";
        }
        // locate the AX alias
        String axAlias = null;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if (name.startsWith("openid.ns.")) {
                if ("http://openid.net/srv/ax/1.0".equals(value)) {
                    axAlias = name.substring("openid.ns.".length());
                    break;
                }
            }
        }
        if (null == axAlias) {
            return "";
        }
        // get set of required AX aliases
        Set requiredAttributeAliases = new HashSet();
        int requiredIdx = -1;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if (name.equals("openid." + axAlias + ".required")) {
                String[] aliases = value.split(",");
                requiredAttributeAliases.addAll(Arrays.asList(aliases));
                requiredIdx = i;
                break;
            }
        }
        // get set of optional AX aliases
        Set optionalAttributeAliases = new HashSet();
        int optionalIdx = -1;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if (name.equals("openid." + axAlias + ".if_available")) {
                String[] aliases = value.split(",");
                optionalAttributeAliases.addAll(Arrays.asList(aliases));
                optionalIdx = i;
                break;
            }
        }
        // remove the attribute
        String attributeAlias = null;
        String attributeType = this.openIdProxyConfig.getRemoveAttributeType();
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if (name.startsWith("openid." + axAlias + ".type.")) {
                if (value.equals(attributeType)) {
                    attributeAlias = name.substring(("openid." + axAlias + ".type.").length());
                    values[i] = null; // remove it
                    break;
                }
            }
        }
        if (null == attributeAlias) {
            return "";
        }
        // remove all references to the attribute alias
        requiredAttributeAliases.remove(attributeAlias);
        Iterator requiredIter = requiredAttributeAliases.iterator();
        String requiredValue = "";
        while (requiredIter.hasNext()) {
            requiredValue += (String) requiredIter.next();
            if (requiredIter.hasNext()) {
                requiredValue += ",";
            }
        }
        values[requiredIdx] = new NamedValue(values[requiredIdx].getName(), requiredValue);

        optionalAttributeAliases.remove(attributeAlias);
        Iterator optionalIter = optionalAttributeAliases.iterator();
        String optionalValue = "";
        while (optionalIter.hasNext()) {
            optionalValue += (String) optionalIter.next();
            if (optionalIter.hasNext()) {
                optionalValue += ",";
            }
        }
        values[optionalIdx] = new NamedValue(values[optionalIdx].getName(), optionalValue);

        updateParameters(values, request);
        return "removed attribute request;";
    }

    private String appendAttribute(Request request) {
        NamedValue[] values = getParameters(request);
        if (null == values) {
            return "";
        }
        // check if openid response
        boolean response = false;
        for (int idx = 0; idx < values.length; idx++) {
            String name = values[idx].getName();
            String value = Encoding.urlDecode(values[idx].getValue());
            if ("openid.mode".equals(name)) {
                if ("id_res".equals(value)) {
                    response = true;
                    break;
                }
            }
        }
        if (false == response) {
            return "";
        }
        // check if AX response is present
        String axAlias = null;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if (name.startsWith("openid.ns.")) {
                if ("http://openid.net/srv/ax/1.0".equals(value)) {
                    axAlias = name.substring("openid.ns.".length());
                    break;
                }
            }
        }
        List additionalParameters = new LinkedList();
        if (null == axAlias) {
            axAlias = "ax";
            additionalParameters.add(new NamedValue("openid.ns." + axAlias, "http://openid.net/srv/ax/1.0"));
            additionalParameters.add(new NamedValue("openid." + axAlias + ".mode", "fetch_response"));
        }
        String attributeAlias = this.openIdProxyConfig.getAppendAttributeAlias();
        String attributeType = this.openIdProxyConfig.getAppendAttributeType();
        String attributeValue = this.openIdProxyConfig.getAppendAttributeValue();
        additionalParameters.add(new NamedValue("openid." + axAlias + ".type." + attributeAlias, Encoding.urlEncode(attributeType)));
        additionalParameters.add(new NamedValue("openid." + axAlias + ".value." + attributeAlias, Encoding.urlEncode(attributeValue)));
       
        updateParameters(values, additionalParameters, request);
        return "add attribute response;";
    }
}
TOP

Related Classes of org.owasp.webscarab.plugin.openid.OpenIdHTTPClient

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.