Package org.picketlink.identity.federation.core.parsers.util

Source Code of org.picketlink.identity.federation.core.parsers.util.SAMLParserUtil

/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.picketlink.identity.federation.core.parsers.util;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.picketlink.identity.federation.PicketLinkLogger;
import org.picketlink.identity.federation.PicketLinkLoggerFactory;
import org.picketlink.identity.federation.core.exceptions.ParsingException;
import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLConstants;
import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLURIConstants;
import org.picketlink.identity.federation.core.saml.v2.util.XMLTimeUtil;
import org.picketlink.identity.federation.core.util.StringUtil;
import org.picketlink.identity.federation.core.util.XMLSignatureUtil;
import org.picketlink.identity.federation.core.wstrust.WSTrustConstants;
import org.picketlink.identity.federation.saml.v2.assertion.AttributeStatementType;
import org.picketlink.identity.federation.saml.v2.assertion.AttributeStatementType.ASTChoiceType;
import org.picketlink.identity.federation.saml.v2.assertion.AttributeType;
import org.picketlink.identity.federation.saml.v2.assertion.AuthnContextClassRefType;
import org.picketlink.identity.federation.saml.v2.assertion.AuthnContextDeclRefType;
import org.picketlink.identity.federation.saml.v2.assertion.AuthnContextDeclType;
import org.picketlink.identity.federation.saml.v2.assertion.AuthnContextType;
import org.picketlink.identity.federation.saml.v2.assertion.AuthnContextType.AuthnContextTypeSequence;
import org.picketlink.identity.federation.saml.v2.assertion.AuthnStatementType;
import org.picketlink.identity.federation.saml.v2.assertion.NameIDType;
import org.picketlink.identity.federation.saml.v2.assertion.SubjectLocalityType;
import org.picketlink.identity.xmlsec.w3.xmldsig.DSAKeyValueType;
import org.picketlink.identity.xmlsec.w3.xmldsig.KeyInfoType;
import org.picketlink.identity.xmlsec.w3.xmldsig.KeyValueType;
import org.picketlink.identity.xmlsec.w3.xmldsig.RSAKeyValueType;
import org.picketlink.identity.xmlsec.w3.xmldsig.X509CertificateType;
import org.picketlink.identity.xmlsec.w3.xmldsig.X509DataType;
import org.w3c.dom.Element;

/**
* Utility methods for SAML Parser
*
* @author Anil.Saldhana@redhat.com
* @since Nov 4, 2010
*/
public class SAMLParserUtil {

    private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();

    public static KeyInfoType parseKeyInfo(XMLEventReader xmlEventReader) throws ParsingException {
        KeyInfoType keyInfo = new KeyInfoType();
        StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.KEYINFO);

        XMLEvent xmlEvent = null;
        String tag = null;

        while (xmlEventReader.hasNext()) {
            xmlEvent = StaxParserUtil.peek(xmlEventReader);
            if (xmlEvent instanceof EndElement) {
                tag = StaxParserUtil.getEndElementName((EndElement) xmlEvent);
                if (tag.equals(WSTrustConstants.XMLDSig.KEYINFO)) {
                    xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader);
                    break;
                } else
                    throw logger.parserUnknownEndElement(tag);
            }
            startElement = (StartElement) xmlEvent;
            tag = StaxParserUtil.getStartElementName(startElement);
            if (tag.equals(WSTrustConstants.XMLEnc.ENCRYPTED_KEY)) {
                keyInfo.addContent(StaxParserUtil.getDOMElement(xmlEventReader));
            } else if (tag.equals(WSTrustConstants.XMLDSig.X509DATA)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                X509DataType x509 = new X509DataType();

                // Let us go for the X509 certificate
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.X509CERT);

                X509CertificateType cert = new X509CertificateType();
                String certValue = StaxParserUtil.getElementText(xmlEventReader);
                cert.setEncodedCertificate(certValue.getBytes());
                x509.add(cert);

                EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
                StaxParserUtil.validate(endElement, WSTrustConstants.XMLDSig.X509DATA);
                keyInfo.addContent(x509);
            } else if (tag.equals(WSTrustConstants.XMLDSig.KEYVALUE)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                KeyValueType keyValue = null;

                startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
                tag = StaxParserUtil.getStartElementName(startElement);
                if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) {
                    keyValue = parseRSAKeyValue(xmlEventReader);
                } else if (tag.equals(WSTrustConstants.XMLDSig.DSA_KEYVALUE)) {
                    keyValue = parseDSAKeyValue(xmlEventReader);
                } else
                    throw logger.parserUnknownTag(tag, startElement.getLocation());

                EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
                StaxParserUtil.validate(endElement, WSTrustConstants.XMLDSig.KEYVALUE);

                keyInfo.addContent(keyValue);
            }
        }
        return keyInfo;
    }

    private static RSAKeyValueType parseRSAKeyValue(XMLEventReader xmlEventReader) throws ParsingException {
        StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.RSA_KEYVALUE);

        XMLEvent xmlEvent = null;
        String tag = null;

        RSAKeyValueType rsaKeyValue = new RSAKeyValueType();

        while (xmlEventReader.hasNext()) {
            xmlEvent = StaxParserUtil.peek(xmlEventReader);
            if (xmlEvent instanceof EndElement) {
                tag = StaxParserUtil.getEndElementName((EndElement) xmlEvent);
                if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) {
                    xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader);
                    break;
                } else
                    throw logger.parserUnknownEndElement(tag);
            }

            startElement = (StartElement) xmlEvent;
            tag = StaxParserUtil.getStartElementName(startElement);
            if (tag.equals(WSTrustConstants.XMLDSig.MODULUS)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                String text = StaxParserUtil.getElementText(xmlEventReader);
                rsaKeyValue.setModulus(text.getBytes());
            } else if (tag.equals(WSTrustConstants.XMLDSig.EXPONENT)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                String text = StaxParserUtil.getElementText(xmlEventReader);
                rsaKeyValue.setExponent(text.getBytes());
            } else
                throw logger.parserUnknownTag(tag, startElement.getLocation());
        }
        return rsaKeyValue;
    }
   
    private static DSAKeyValueType parseDSAKeyValue(XMLEventReader xmlEventReader) throws ParsingException {
        StartElement startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
        StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.DSA_KEYVALUE);
       
        Element dsaElement = StaxParserUtil.getDOMElement(xmlEventReader);
        return XMLSignatureUtil.getDSAKeyValue(dsaElement);
    }

    /**
     * Parse an {@code AttributeStatementType}
     *
     * @param xmlEventReader
     * @return
     * @throws ParsingException
     */
    public static AttributeStatementType parseAttributeStatement(XMLEventReader xmlEventReader) throws ParsingException {
        AttributeStatementType attributeStatementType = new AttributeStatementType();

        StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        String ATTRIBSTATEMT = JBossSAMLConstants.ATTRIBUTE_STATEMENT.get();
        StaxParserUtil.validate(startElement, ATTRIBSTATEMT);

        while (xmlEventReader.hasNext()) {
            XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
            if (xmlEvent instanceof EndElement) {
                EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
                StaxParserUtil.validate(endElement, JBossSAMLConstants.ATTRIBUTE_STATEMENT.get());
                break;
            }
            // Get the next start element
            startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
            String tag = startElement.getName().getLocalPart();
            if (JBossSAMLConstants.ATTRIBUTE.get().equals(tag)) {
                AttributeType attribute = parseAttribute(xmlEventReader);
                attributeStatementType.addAttribute(new ASTChoiceType(attribute));
            } else
                throw logger.parserUnknownTag(tag, startElement.getLocation());
        }
        return attributeStatementType;
    }

    /**
     * Parse an {@code AttributeType}
     *
     * @param xmlEventReader
     * @return
     * @throws ParsingException
     */
    public static AttributeType parseAttribute(XMLEventReader xmlEventReader) throws ParsingException {
        StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE.get());
        AttributeType attributeType = null;

        Attribute name = startElement.getAttributeByName(new QName(JBossSAMLConstants.NAME.get()));
        if (name == null)
            throw logger.parserRequiredAttribute("Name");
        attributeType = new AttributeType(StaxParserUtil.getAttributeValue(name));

        parseAttributeType(xmlEventReader, startElement, JBossSAMLConstants.ATTRIBUTE.get(), attributeType);

        return attributeType;
    }

    /**
     * Parse an {@code AttributeType}
     *
     * @param xmlEventReader
     * @throws ParsingException
     */
    public static void parseAttributeType(XMLEventReader xmlEventReader, StartElement startElement, String rootTag,
            AttributeType attributeType) throws ParsingException {
        // Look for X500 Encoding
        QName x500EncodingName = new QName(JBossSAMLURIConstants.X500_NSURI.get(), JBossSAMLConstants.ENCODING.get(),
                JBossSAMLURIConstants.X500_PREFIX.get());
        Attribute x500EncodingAttr = startElement.getAttributeByName(x500EncodingName);

        if (x500EncodingAttr != null) {
            attributeType.getOtherAttributes().put(x500EncodingAttr.getName(),
                    StaxParserUtil.getAttributeValue(x500EncodingAttr));
        }

        Attribute friendlyName = startElement.getAttributeByName(new QName(JBossSAMLConstants.FRIENDLY_NAME.get()));
        if (friendlyName != null)
            attributeType.setFriendlyName(StaxParserUtil.getAttributeValue(friendlyName));

        Attribute nameFormat = startElement.getAttributeByName(new QName(JBossSAMLConstants.NAME_FORMAT.get()));
        if (nameFormat != null)
            attributeType.setNameFormat(StaxParserUtil.getAttributeValue(nameFormat));

        while (xmlEventReader.hasNext()) {
            XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
            if (xmlEvent instanceof EndElement) {
                EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
                if (StaxParserUtil.matches(end, rootTag))
                    break;
            }
            startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
            if (startElement == null)
                break;
            String tag = StaxParserUtil.getStartElementName(startElement);

            if (JBossSAMLConstants.ATTRIBUTE.get().equals(tag))
                break;

            if (JBossSAMLConstants.ATTRIBUTE_VALUE.get().equals(tag)) {
                Object attributeValue = parseAttributeValue(xmlEventReader);
                attributeType.addAttributeValue(attributeValue);
            } else
                throw logger.parserUnknownTag(tag, startElement.getLocation());
        }
    }

    /**
     * Parse Attribute value
     *
     * @param xmlEventReader
     * @return
     * @throws ParsingException
     */
    public static Object parseAttributeValue(XMLEventReader xmlEventReader) throws ParsingException {
        StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE_VALUE.get());

        Attribute type = startElement.getAttributeByName(new QName(JBossSAMLURIConstants.XSI_NSURI.get(), "type", "xsi"));
        if (type == null) {
          if(StaxParserUtil.hasTextAhead(xmlEventReader)){
            return StaxParserUtil.getElementText(xmlEventReader);
          }
          //Else we may have Child Element
          XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
          if(xmlEvent instanceof StartElement){
            startElement = (StartElement) xmlEvent;
            String tag = StaxParserUtil.getStartElementName(startElement);
            if(tag.equals(JBossSAMLConstants.NAMEID.get())){
              return parseNameIDType(xmlEventReader);
            }
          }
          throw logger.unsupportedType(StaxParserUtil.getStartElementName(startElement));
        }

        String typeValue = StaxParserUtil.getAttributeValue(type);
        if (typeValue.contains(":string")) {
            return StaxParserUtil.getElementText(xmlEventReader);
        } else if (typeValue.contains(":anyType")) {
            // TODO: for now assume that it is a text value that can be parsed and set as the attribute value
            return StaxParserUtil.getElementText(xmlEventReader);
        }

        throw logger.parserUnknownXSI(typeValue);
    }

    /**
     * Parse the AuthnStatement inside the assertion
     *
     * @param xmlEventReader
     * @return
     * @throws ParsingException
     */
    public static AuthnStatementType parseAuthnStatement(XMLEventReader xmlEventReader) throws ParsingException {
        StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        String AUTHNSTATEMENT = JBossSAMLConstants.AUTHN_STATEMENT.get();
        StaxParserUtil.validate(startElement, AUTHNSTATEMENT);

        Attribute authnInstant = startElement.getAttributeByName(new QName("AuthnInstant"));
        if (authnInstant == null)
            throw logger.parserRequiredAttribute("AuthnInstant");

        XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(authnInstant));
        AuthnStatementType authnStatementType = new AuthnStatementType(issueInstant);

        Attribute sessionIndex = startElement.getAttributeByName(new QName("SessionIndex"));
        if (sessionIndex != null)
            authnStatementType.setSessionIndex(StaxParserUtil.getAttributeValue(sessionIndex));

        while (xmlEventReader.hasNext()) {
            XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
            if (xmlEvent == null)
                break;

            if (xmlEvent instanceof EndElement) {
                xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
                EndElement endElement = (EndElement) xmlEvent;
                String endElementTag = StaxParserUtil.getEndElementName(endElement);
                if (endElementTag.equals(AUTHNSTATEMENT))
                    break;
                else
                    throw logger.parserUnknownEndElement(endElementTag);
            }
            startElement = null;

            if (xmlEvent instanceof StartElement) {
                startElement = (StartElement) xmlEvent;
            } else {
                startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
            }
            if (startElement == null)
                break;

            String tag = StaxParserUtil.getStartElementName(startElement);

            if (JBossSAMLConstants.SUBJECT_LOCALITY.get().equals(tag)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                SubjectLocalityType subjectLocalityType = new SubjectLocalityType();
                Attribute address = startElement.getAttributeByName(new QName(JBossSAMLConstants.ADDRESS.get()));
                if (address != null) {
                    subjectLocalityType.setAddress(StaxParserUtil.getAttributeValue(address));
                }
                Attribute dns = startElement.getAttributeByName(new QName(JBossSAMLConstants.DNS_NAME.get()));
                if (dns != null) {
                    subjectLocalityType.setDNSName(StaxParserUtil.getAttributeValue(dns));
                }
                authnStatementType.setSubjectLocality(subjectLocalityType);
                StaxParserUtil.validate(StaxParserUtil.getNextEndElement(xmlEventReader),
                        JBossSAMLConstants.SUBJECT_LOCALITY.get());
            } else if (JBossSAMLConstants.AUTHN_CONTEXT.get().equals(tag)) {
                authnStatementType.setAuthnContext(parseAuthnContextType(xmlEventReader));
            } else
                throw logger.parserUnknownTag(tag, startElement.getLocation());

        }

        return authnStatementType;
    }

    /**
     * Parse the AuthnContext Type inside the AuthnStatement
     *
     * @param xmlEventReader
     * @return
     * @throws ParsingException
     */
    public static AuthnContextType parseAuthnContextType(XMLEventReader xmlEventReader) throws ParsingException {
        AuthnContextType authnContextType = new AuthnContextType();

        StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        StaxParserUtil.validate(startElement, JBossSAMLConstants.AUTHN_CONTEXT.get());

        while (xmlEventReader.hasNext()) {
            XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
            if (xmlEvent == null)
                break;

            if (xmlEvent instanceof EndElement) {
                xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
                EndElement endElement = (EndElement) xmlEvent;
                String endElementTag = StaxParserUtil.getEndElementName(endElement);
                if (endElementTag.equals(JBossSAMLConstants.AUTHN_CONTEXT.get()))
                    break;
                else
                    throw logger.parserUnknownEndElement(endElementTag);
            }
            startElement = null;

            if (xmlEvent instanceof StartElement) {
                startElement = (StartElement) xmlEvent;
            } else {
                startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
            }
            if (startElement == null)
                break;

            String tag = StaxParserUtil.getStartElementName(startElement);

            if (JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get().equals(tag)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);

                Element dom = StaxParserUtil.getDOMElement(xmlEventReader);

                AuthnContextDeclType authnContextDecl = new AuthnContextDeclType(dom);
                AuthnContextTypeSequence authnContextSequence = authnContextType.new AuthnContextTypeSequence();
                authnContextSequence.setAuthnContextDecl(authnContextDecl);
                authnContextType.setSequence(authnContextSequence);

                EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
                StaxParserUtil.validate(endElement, JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get());
            } else if (JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION_REF.get().equals(tag)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                String text = StaxParserUtil.getElementText(xmlEventReader);

                AuthnContextDeclRefType aAuthnContextDeclType = new AuthnContextDeclRefType(URI.create(text));
                authnContextType.addURIType(aAuthnContextDeclType);
            } else if (JBossSAMLConstants.AUTHN_CONTEXT_CLASS_REF.get().equals(tag)) {
                startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
                String text = StaxParserUtil.getElementText(xmlEventReader);

                AuthnContextClassRefType aAuthnContextClassRefType = new AuthnContextClassRefType(URI.create(text));
                AuthnContextTypeSequence authnContextSequence = authnContextType.new AuthnContextTypeSequence();
                authnContextSequence.setClassRef(aAuthnContextClassRefType);

                authnContextType.setSequence(authnContextSequence);
            } else
                throw logger.parserUnknownTag(tag, startElement.getLocation());
        }

        return authnContextType;
    }

    /**
     * Parse a {@code NameIDType}
     *
     * @param xmlEventReader
     * @return
     * @throws ParsingException
     */
    public static NameIDType parseNameIDType(XMLEventReader xmlEventReader) throws ParsingException {
        StartElement nameIDElement = StaxParserUtil.getNextStartElement(xmlEventReader);
        NameIDType nameID = new NameIDType();

        Attribute nameQualifier = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.NAME_QUALIFIER.get()));
        if (nameQualifier != null) {
            nameID.setNameQualifier(StaxParserUtil.getAttributeValue(nameQualifier));
        }

        Attribute format = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.FORMAT.get()));
        if (format != null) {
            nameID.setFormat(URI.create(StaxParserUtil.getAttributeValue(format)));
        }

        Attribute spProvidedID = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.SP_PROVIDED_ID.get()));
        if (spProvidedID != null) {
            nameID.setSPProvidedID(StaxParserUtil.getAttributeValue(spProvidedID));
        }

        Attribute spNameQualifier = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.SP_NAME_QUALIFIER.get()));
        if (spNameQualifier != null) {
            nameID.setSPNameQualifier(StaxParserUtil.getAttributeValue(spNameQualifier));
        }

        String nameIDValue = StaxParserUtil.getElementText(xmlEventReader);
        nameID.setValue(nameIDValue);

        return nameID;
    }

    /**
     * Parse a space delimited list of strings
     *
     * @param startElement
     * @return
     */
    public static List<String> parseProtocolEnumeration(StartElement startElement) {
        List<String> protocolEnum = new ArrayList<String>();
        Attribute proto = startElement.getAttributeByName(new QName(JBossSAMLConstants.PROTOCOL_SUPPORT_ENUMERATION.get()));
        String val = StaxParserUtil.getAttributeValue(proto);
        if (StringUtil.isNotNull(val)) {
            StringTokenizer st = new StringTokenizer(val);
            while (st.hasMoreTokens()) {
                protocolEnum.add(st.nextToken());
            }

        }
        return protocolEnum;
    }
}
TOP

Related Classes of org.picketlink.identity.federation.core.parsers.util.SAMLParserUtil

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.