Package org.owasp.webscarab.plugin.openid

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

/***********************************************************************
*
* 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.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.crypto.spec.DHParameterSpec;
import org.openid4java.association.Association;
import org.openid4java.association.AssociationSessionType;
import org.openid4java.association.DiffieHellmanSession;
import org.openid4java.message.AssociationRequest;
import org.openid4java.message.AssociationResponse;
import org.openid4java.message.ParameterList;
import org.owasp.webscarab.httpclient.HTTPClientFactory;
import org.owasp.webscarab.model.ConversationID;
import org.owasp.webscarab.model.ConversationModel;
import org.owasp.webscarab.model.FilteredConversationModel;
import org.owasp.webscarab.model.FrameworkModel;
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.plugin.AbstractPluginModel;
import org.owasp.webscarab.util.Encoding;

/**
*
* @author Frank Cornelis
*/
public class OpenIdModel extends AbstractPluginModel {

    private Logger _logger = Logger.getLogger(getClass().getName());
    private final FrameworkModel model;
    private final ConversationModel openIdConversationModel;

    public OpenIdModel(FrameworkModel model) {
        this.model = model;
        this.openIdConversationModel = new FilteredConversationModel(model, model.getConversationModel()) {

            @Override
            public boolean shouldFilter(ConversationID id) {
                return !isOpenIDMessage(id);
            }
        };
    }

    public void setOpenIDMessage(ConversationID id, String namespace) {
        this.model.setConversationProperty(id, "OPENID", namespace);
    }

    public boolean isOpenIDMessage(ConversationID id) {
        return this.model.getConversationProperty(id, "OPENID") != null;
    }

    public ConversationModel getOpenIDConversationModel() {
        return this.openIdConversationModel;
    }

    public void setOpenIDMessageType(ConversationID id, String messageType) {
        this.model.setConversationProperty(id, "OPENID_MODE", messageType);
    }

    public String getReadableOpenIDMessageType(ConversationID id) {
        String openIdMode = this.model.getConversationProperty(id, "OPENID_MODE");
        if (null == openIdMode) {
            return "Unknown";
        }
        if ("checkid_setup".equals(openIdMode)) {
            return "Request";
        }
        if ("id_res".equals(openIdMode)) {
            return "Response";
        }
        return "Unknown";
    }

    public List getParameters(ConversationID id) {
        List parameters = new LinkedList();
        Request request = this.model.getRequest(id);
        NamedValue[] values = null;
        String method = request.getMethod();
        if ("GET".equals(method)) {
            HttpUrl url = request.getURL();
            String query = url.getQuery();
            if (null != query) {
                values = NamedValue.splitNamedValues(query, "&", "=");
            }
        } else if ("POST".equals(method)) {
            byte[] requestContent = request.getContent();
            if (requestContent != null && requestContent.length > 0) {
                String body = new String(requestContent);
                values = NamedValue.splitNamedValues(
                        body, "&", "=");
            }
        }
        if (null != values) {
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.startsWith("openid.")) {
                    NamedValue parameter = new NamedValue(name, value);
                    parameters.add(parameter);
                }
            }
        }
        return parameters;
    }

    public List getAXFetchRequestAttributes(ConversationID id) {
        List attributes = new LinkedList();
        Request request = this.model.getRequest(id);
        String method = request.getMethod();
        NamedValue[] values = null;
        if ("GET".equals(method)) {
            HttpUrl url = request.getURL();
            String query = url.getQuery();
            if (null != query) {
                values = NamedValue.splitNamedValues(query, "&", "=");
            }
        } else if ("POST".equals(method)) {
            byte[] requestContent = request.getContent();
            if (requestContent != null && requestContent.length > 0) {
                String body = new String(requestContent);
                values = NamedValue.splitNamedValues(
                        body, "&", "=");
            }
        }
        if (null != values) {
            // first locate the AX extension
            String alias = 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)) {
                        alias = name.substring("openid.ns.".length());
                        break;
                    }
                }
            }
            if (null == alias) {
                return attributes;
            }
            _logger.info("AX alias: " + alias);
            // check the AX mode
            boolean isFetchRequest = false;
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.equals("openid." + alias + ".mode")) {
                    if ("fetch_request".equals(value)) {
                        isFetchRequest = true;
                        break;
                    }
                }
            }
            if (false == isFetchRequest) {
                return attributes;
            }
            // required aliases
            Set requiredAliases = new HashSet();
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.equals("openid." + alias + ".required")) {
                    String[] aliases = value.split(",");
                    requiredAliases.addAll(Arrays.asList(aliases));
                    break;
                }
            }
            // optional aliases
            Set optionalAliases = new HashSet();
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.equals("openid." + alias + ".if_available")) {
                    String[] aliases = value.split(",");
                    optionalAliases.addAll(Arrays.asList(aliases));
                    break;
                }
            }
            // get the fetch request attributes
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.startsWith("openid." + alias + ".type.")) {
                    String attributeAlias = name.substring(("openid." + alias + ".type.").length());
                    boolean requiredAttribute = requiredAliases.contains(attributeAlias);
                    boolean optionalAttribute = optionalAliases.contains(attributeAlias);
                    AXFetchRequestAttribute attribute = new AXFetchRequestAttribute(value, attributeAlias, requiredAttribute, optionalAttribute);
                    attributes.add(attribute);
                }
            }
        }
        return attributes;
    }

    public List getAXFetchResponseAttributes(ConversationID id) {
        List attributes = new LinkedList();
        Request request = this.model.getRequest(id);
        String method = request.getMethod();
        NamedValue[] values = null;
        if ("GET".equals(method)) {
            HttpUrl url = request.getURL();
            String query = url.getQuery();
            if (null != query) {
                values = NamedValue.splitNamedValues(query, "&", "=");
            }
        } else if ("POST".equals(method)) {
            byte[] requestContent = request.getContent();
            if (requestContent != null && requestContent.length > 0) {
                String body = new String(requestContent);
                values = NamedValue.splitNamedValues(
                        body, "&", "=");
            }
        }
        if (null != values) {
            // first locate the AX extension
            String alias = 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)) {
                        alias = name.substring("openid.ns.".length());
                        break;
                    }
                }
            }
            if (null == alias) {
                return attributes;
            }
            _logger.info("AX alias: " + alias);
            // check the AX mode
            boolean isFetchResponse = false;
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.equals("openid." + alias + ".mode")) {
                    if ("fetch_response".equals(value)) {
                        isFetchResponse = true;
                        break;
                    }
                }
            }
            if (false == isFetchResponse) {
                return attributes;
            }
            // signed aliases
            Set signedAliases = new HashSet();
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.equals("openid.signed")) {
                    String[] aliases = value.split(",");
                    signedAliases.addAll(Arrays.asList(aliases));
                    break;
                }
            }
            // get the fetch response attributes
            Map attributeMap = new HashMap();
            for (int i = 0; i < values.length; i++) {
                String name = values[i].getName();
                String value = Encoding.urlDecode(values[i].getValue());
                if (name.startsWith("openid." + alias + ".type.")) {
                    String attributeAlias = name.substring(("openid." + alias + ".type.").length());
                    AXFetchResponseAttribute attribute = (AXFetchResponseAttribute) attributeMap.get(attributeAlias);
                    if (null == attribute) {
                        attribute = new AXFetchResponseAttribute(attributeAlias);
                        attributeMap.put(attributeAlias, attribute);
                    }
                    attribute.setAttributeType(value);
                } else if (name.startsWith("openid." + alias + ".value.")) {
                    String attributeAlias = name.substring(("openid." + alias + ".value.").length());
                    AXFetchResponseAttribute attribute = (AXFetchResponseAttribute) attributeMap.get(attributeAlias);
                    if (null == attribute) {
                        attribute = new AXFetchResponseAttribute(attributeAlias);
                        attributeMap.put(attributeAlias, attribute);
                    }
                    attribute.setValue(value);
                }
            }
            attributes.addAll(attributeMap.values());
            // check attribute signing
            Iterator attributeIterator = attributes.iterator();
            while (attributeIterator.hasNext()) {
                AXFetchResponseAttribute attribute = (AXFetchResponseAttribute) attributeIterator.next();
                if (signedAliases.contains(alias + ".type." + attribute.getAlias())
                        && signedAliases.contains(alias + ".value." + attribute.getAlias())) {
                    attribute.setSigned(true);
                }
            }
        }
        return attributes;
    }

    public PAPEResponse getPAPEResponse(ConversationID id) {
        Request request = this.model.getRequest(id);
        String method = request.getMethod();
        NamedValue[] values = null;
        if ("GET".equals(method)) {
            HttpUrl url = request.getURL();
            String query = url.getQuery();
            if (null != query) {
                values = NamedValue.splitNamedValues(query, "&", "=");
            }
        } else if ("POST".equals(method)) {
            byte[] requestContent = request.getContent();
            if (requestContent != null && requestContent.length > 0) {
                String body = new String(requestContent);
                values = NamedValue.splitNamedValues(
                        body, "&", "=");
            }
        }
        if (null == values) {
            return null;
        }
        // first locate the PAPE extension
        String alias = 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://specs.openid.net/extensions/pape/1.0".equals(value)) {
                    alias = name.substring("openid.ns.".length());
                    break;
                }
            }
        }
        if (null == alias) {
            return null;
        }
        // signed aliases
        Set signedAliases = new HashSet();
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if (name.equals("openid.signed")) {
                String[] aliases = value.split(",");
                signedAliases.addAll(Arrays.asList(aliases));
                break;
            }
        }
        PAPEResponse papeResponse = new PAPEResponse();
        boolean signed = true;
        for (int i = 0; i < values.length; i++) {
            String name = values[i].getName();
            String value = Encoding.urlDecode(values[i].getValue());
            if (name.startsWith("openid." + alias)) {
                String expectedSignedAlias = name.substring("openid.".length());
                if (false == signedAliases.contains(expectedSignedAlias)) {
                    signed = false;
                }
            }
            if (name.equals("openid." + alias + ".auth_time")) {
                papeResponse.setAuthenticationTime(value);
            } else if (name.equals("openid." + alias + ".auth_policies")) {
                String[] authPolicies = value.split(" ");
                Set authPoliciesSet = new HashSet(Arrays.asList(authPolicies));
                if (authPoliciesSet.contains("http://schemas.openid.net/pape/policies/2007/06/phishing-resistant")) {
                    papeResponse.setPhishingResistant(true);
                }
                if (authPoliciesSet.contains("http://schemas.openid.net/pape/policies/2007/06/multi-factor")) {
                    papeResponse.setMultiFactor(true);
                }
                if (authPoliciesSet.contains("http://schemas.openid.net/pape/policies/2007/06/multi-factor-physical")) {
                    papeResponse.setMultiFactorPhysical(true);
                }
            }
        }
        if (false == signedAliases.contains("ns." + alias)) {
            signed = false;
        }
        papeResponse.setSigned(signed);
        return papeResponse;
    }

    public Association establishAssociation(String opUrl, AssociationSessionType associationSessionType) throws Exception {
        DiffieHellmanSession dhSession;
        if (null != associationSessionType.getHAlgorithm()) {
            // Diffie-Hellman
            DHParameterSpec dhParameterSpec = DiffieHellmanSession.getDefaultParameter();
            dhSession = DiffieHellmanSession.create(associationSessionType,
                    dhParameterSpec);
        } else {
            dhSession = null;
        }
        AssociationRequest associationRequest = AssociationRequest.createAssociationRequest(associationSessionType, dhSession);
        Request request = new Request();
        request.setMethod("POST");
        request.setURL(new HttpUrl(opUrl));
        request.setHeader("Content-Type", "application/x-www-form-urlencoded");

        StringBuilder body = new StringBuilder();
        Map parameters = associationRequest.getParameterMap();
        Set parameterEntries = parameters.entrySet();
        Iterator parameterIterator = parameterEntries.iterator();
        while (parameterIterator.hasNext()) {
            if (0 != body.length()) {
                body.append("&");
            }
            Map.Entry parameterEntry = (Map.Entry) parameterIterator.next();
            body.append(parameterEntry.getKey());
            body.append("=");
            body.append(Encoding.urlEncode((String)parameterEntry.getValue()));
        }
        request.setHeader("Content-Length", Integer.toString(body.length()));
        request.setContent(body.toString().getBytes());

        Response response = HTTPClientFactory.getInstance().fetchResponse(request);
        if (false == "200".equals(response.getStatus())) {
            throw new RuntimeException("invalid status return code: " + response.getStatus());
        }

        byte[] responseContent = response.getContent();
        ParameterList responseParameterList = ParameterList.createFromKeyValueForm(new String(responseContent));
        AssociationResponse associationResponse = AssociationResponse.createAssociationResponse(responseParameterList);

        Association association = associationResponse.getAssociation(dhSession);
        return association;
    }

    public boolean isOpenIDRequestMessage(ConversationID id) {
        String openIdMode = this.model.getConversationProperty(id, "OPENID_MODE");
        if (null == openIdMode) {
            return false;
        }
        if ("checkid_setup".equals(openIdMode)) {
            return true;
        }
        return false;
    }

    public String getOPUrl(ConversationID id) {
        if (false == isOpenIDRequestMessage(id)) {
            return null;
        }
        HttpUrl httpUrl = this.model.getRequestUrl(id);
        return httpUrl.getSHPP();
    }
}
TOP

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

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.