Package com.google.gsa.valve.saml.authn

Source Code of com.google.gsa.valve.saml.authn.SAMLAuthNResolve$ArtifactRequest

/**
  * Copyright (C) 2008 Google - Enterprise EMEA SE
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  * License for the specific language governing permissions and limitations under
  * the License.
  */

package com.google.gsa.valve.saml.authn;

import com.google.gsa.valve.saml.ArtifactTimer;
import com.google.gsa.valve.configuration.ValveConfiguration;
import com.google.gsa.valve.configuration.ValveConfigurationException;
import com.google.gsa.valve.configuration.ValveConfigurationInstance;
import com.google.gsa.valve.saml.SAMLArtifactProcessor;
import com.google.gsa.valve.saml.XmlProcessingException;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Writer;

import java.net.InetAddress;

import java.text.SimpleDateFormat;

import java.util.Date;
import java.util.TimeZone;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.impl.OMNamespaceImpl;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
import org.apache.log4j.Logger;

/**
* Processes the authentication resolve request. This is sent by the client
* component (appliance) to verify the authentication process was succesful
* and the unique identifier of the authenticated user.
*
*/
public class SAMLAuthNResolve extends HttpServlet {

    static final String SOAP_ENV_NS =
        "http://schemas.xmlsoap.org/soap/envelope/";
    static final String SAML_NS = "urn:oasis:names:tc:SAML:2.0:assertion";
    static final String SAMLP_NS = "urn:oasis:names:tc:SAML:2.0:protocol";

    static final String SAML_STATUS_CODE_SUCCESS =
        "urn:oasis:names:tc:SAML:2.0:status:Success";
    static final String SAML_STATUS_CODE_REQUESTER =
        "urn:oasis:names:tc:SAML:2.0:status:Requester";
    static final String SAML_STATUS_CODE_RESPONDER =
        "urn:oasis:names:tc:SAML:2.0:status:Responder";

    //Encoding
    private static final String encoding = "UTF-8";

    //Date Format
    private static final SimpleDateFormat dateFormat =
        new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH:mm:ss'Z'");
    // Seconds in minutes for conversion.
    private static final long SECS_IN_MIN = 60;
    // Milliseconds in seconds for conversion.
    private static final long MSECS_IN_SEC = 1000;

    //Default username
    private static final String DEFAULT_USERNAME = "default_user";

    //SAML Timeout
    private static Long samlTimeout = null;

    //Artifact timer
    ArtifactTimer artifactTimer;

    //SAMLUserAuthentication
    private SAMLUserAuthentication userAuthentication = null;

    //Logger
    private static Logger logger = Logger.getLogger(SAMLAuthNResolve.class);

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods. It gets the SAML request from the appliance and processes it
     * accordingly.
     *
     * @param request HTTP request
     * @param response HTTP response
     */
    protected void processRequest(HttpServletRequest request,
                                  HttpServletResponse response) throws ServletException,
                                                                       IOException {

        logger.debug("SAMLAuthNResolve:processRequest");

        //ArtifactTimer
        artifactTimer = ArtifactTimer.getInstance();
        artifactTimer.setTimer();

        response.setContentType("text/xml;charset=" + encoding);

        String buildStatus = SAML_STATUS_CODE_SUCCESS;

        ArtifactRequest artifactRequest = null;

        try {
            artifactRequest = extractDataFromRequest(request);
        } catch (XmlProcessingException ex) {
            logger.error("Bad input XML string - will respond " +
                         SAML_STATUS_CODE_REQUESTER, ex);
            buildStatus = SAML_STATUS_CODE_REQUESTER;
        } catch (Exception ex) {
            logger.error("Bad input XML string - unable to respond", ex);
            throw new ServletException(ex);
        }

        PrintWriter out = response.getWriter();

        String userName = null;
        if (artifactRequest != null) {
            userAuthentication =
                    SAMLArtifactProcessor.getInstance().consumeArtifact(artifactRequest.getArtifact());
            userName = userAuthentication.getUserName();
        } else {
            artifactRequest = new ArtifactRequest();
        }

        logger.debug("ArtifactResolve received with ID=\"" +
                     artifactRequest.getId() + "\"" + " for artifact=\"" +
                     artifactRequest.getArtifact() + "\"" +
                     ", responding userName=\"" + userName + "\"");

        try {
            buildResponse(buildStatus, out, artifactRequest, userName);
        } catch (Exception ex) {
            logger.error("Problems generating SOAP response - unable to respond",
                         ex);
            throw new ServletException(ex);
        }

        out.close();
    }

    /**
     * Servlet's doGet
     *
     * @param request HTTP request
     * @param response HTTP response
     *
     * @throws ServletException
     * @throws IOException
     */
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException,
                                                              IOException {
        processRequest(request, response);
    }

    /**
     * Servlet's doPost
     *
     * @param request HTTP request
     * @param response HTTP response
     *
     * @throws ServletException
     * @throws IOException
     */
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) throws ServletException,
                                                               IOException {
        processRequest(request, response);
    }

    /**
     * Extracts SAML from the XML message sent in the request
     *
     * @param request HTTP request
     *
     * @return artifact request
     *
     * @throws IOException
     * @throws XMLStreamException
     * @throws XmlProcessingException
     */
    private ArtifactRequest extractDataFromRequest(HttpServletRequest request) throws IOException,
                                                                                      XMLStreamException,
                                                                                      XmlProcessingException {
        InputStream is = request.getInputStream();
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader reader = xif.createXMLStreamReader(is);
        StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(reader);

        QName qName = null;
        try {
            qName = new QName(SAMLP_NS, "ArtifactResolve");
            OMElement artifactResolve =
                builder.getSOAPEnvelope().getBody().getFirstChildWithName(qName);
            checkNotNull(artifactResolve);
            qName = new QName(null, "ID");
            OMAttribute id = artifactResolve.getAttribute(qName);
            checkNotNull(id);
            qName = new QName(null, "IssueInstant");
            OMAttribute issueInstant = artifactResolve.getAttribute(qName);
            checkNotNull(issueInstant);
            qName = new QName(SAMLP_NS, "Artifact");
            OMElement artifact = artifactResolve.getFirstChildWithName(qName);
            checkNotNull(artifact);

            return new ArtifactRequest(id.getAttributeValue(),
                                       artifact.getText(),
                                       issueInstant.getAttributeValue());
        } catch (NullPointerException ex) {
            throw new XmlProcessingException(qName +
                                             " not found while processing SAML ArtifactResolve request");
        } catch (Exception ex) {
            throw new XmlProcessingException(qName +
                                             " not found while processing SAML ArtifactResolve request",
                                             ex);
        }

    }

    /**
     * Calculates the expire time based on the timeout and the creation time
     *
     * @param creationTime creation time
     * @param samlTimeout saml timeout
     *
     * @return the expiration date
     */
    private String getExpireTime(long creationTime, long samlTimeout) {

        //Note: creationTime is coming in secs
        long expireTime;
        Date dateExp;
        String strDateExp = null;

        //transform samlTimeout to secs
        samlTimeout = samlTimeout * SECS_IN_MIN;

        //Get Expire Date as String
        try {
            expireTime = (creationTime + samlTimeout) * MSECS_IN_SEC;
            dateExp = new Date(expireTime);
            //Set Time Zone
            dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
            strDateExp = dateFormat.format(dateExp).toString();
            logger.debug("Expire date: " + strDateExp);
        } catch (Exception e) {
            logger.error("Date error: " + e);
        }

        return strDateExp;
    }

    /**
     * Gets current date as a String
     *
     * @return the current date
     */
    private String getCurrentDate() {

        String strCurrentDate = null;

        //Get current Date as String
        try {
            long currentTimeMillis = System.currentTimeMillis();
            Date currentDate = new Date(currentTimeMillis);
            //Set Time Zone
            dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
            strCurrentDate = dateFormat.format(currentDate);
        } catch (Exception e) {
            logger.error("Date error: " + e);
        }

        return strCurrentDate;
    }

    /**
     * Builds the SAML response to be sent to the caller
     *
     * @param buildStatus status
     * @param writer servlet writer
     * @param artifactRequest artifact request
     * @param userName user ID
     *
     * @throws XMLStreamException
     */
    private void buildResponse(String buildStatus, Writer writer,
                               ArtifactRequest artifactRequest,
                               String userName) throws XMLStreamException {

        logger.debug("SAMLAuthNResolve::buildResponse");

        String requestId = null;
        if (artifactRequest != null) {
            requestId = artifactRequest.getId();
        }

        SOAPFactory factory = OMAbstractFactory.getSOAP12Factory();
        SOAPEnvelope soapEnvelope = factory.createSOAPEnvelope();
        soapEnvelope.setNamespace(new OMNamespaceImpl(SOAP_ENV_NS, "soapenv"));
        soapEnvelope.addAttribute("xmlns:xsd",
                                  "http://www.w3.org/2001/XMLSchema", null);
        soapEnvelope.addAttribute("xmlns:xsi",
                                  "http://www.w3.org/2001/XMLSchema-instance",
                                  null);
        SOAPBody soapBody = factory.createSOAPBody(soapEnvelope);

        String issuerName = "unknown";

        String strCurrentDate = "unknown";
        String strExpireDate = "unknown";

        try {

            if (userName == null) {
                userName = DEFAULT_USERNAME;
                if (userName != null) {
                    userName = userName.trim();
                }
            }

            InetAddress addr = InetAddress.getLocalHost();
            issuerName = addr.getHostName();


        } catch (Exception ex) {
            buildStatus = SAML_STATUS_CODE_RESPONDER;
            logger.error("Problems building response - will respond " +
                         buildStatus, ex);
        }

        strCurrentDate = getCurrentDate();
        strExpireDate =
                getExpireTime(userAuthentication.getTime(), getSamlTimeout());


        // build the SAML stuff
        OMNamespace samlp =
            factory.createOMNamespace("urn:oasis:names:tc:SAML:2.0:protocol",
                                      "samlp");

        OMElement artifactResponse =
            factory.createOMElement("ArtifactResponse", samlp, soapBody);
        OMNamespace saml =
            artifactResponse.declareDefaultNamespace("urn:oasis:names:tc:SAML:2.0:assertion");
        artifactResponse.addAttribute("ID", "foo1", null);
        artifactResponse.addAttribute("Version", "2.0", null);
        artifactResponse.addAttribute("InResponseTo", "Unspecified", null);
        artifactResponse.addAttribute("IssueInstant",
                                      artifactRequest.getIssueInstant(), null);


        //namespace
        OMElement issuer =
            factory.createOMElement("Issuer", saml, artifactResponse);
        issuer.addAttribute("xmlns", "urn:oasis:names:tc:SAML:2.0:assertion",
                            null);
        issuer.setText(issuerName);


        OMElement status =
            factory.createOMElement("Status", samlp, artifactResponse);
        OMElement statusCode =
            factory.createOMElement("StatusCode", samlp, status);
        statusCode.addAttribute("Value", buildStatus, null);

        if (buildStatus == SAML_STATUS_CODE_SUCCESS && userName != null) {
            OMElement response =
                factory.createOMElement("Response", samlp, artifactResponse);
            response.addAttribute("ID", "foo2", null);
            response.addAttribute("Version", "2.0", null);
            response.addAttribute("IssueInstant", strCurrentDate, null);

            status = factory.createOMElement("Status", samlp, response);
            statusCode = factory.createOMElement("StatusCode", samlp, status);
            statusCode.addAttribute("Value", buildStatus, null);

            OMElement assertion =
                factory.createOMElement("Assertion", saml, response);
            assertion.addAttribute("xmlns",
                                   "urn:oasis:names:tc:SAML:2.0:assertion",
                                   null);

            assertion.addAttribute("ID", "foo3", null);
            assertion.addAttribute("Version", "2.0", null);
            assertion.addAttribute("IssueInstant", strCurrentDate, null);

            issuer = factory.createOMElement("Issuer", saml, assertion);
            issuer.setText(issuerName);

            OMElement subject =
                factory.createOMElement("Subject", saml, assertion);

            OMElement nameID =
                factory.createOMElement("NameID", saml, subject);


            String nameIdSubject = userName;

            nameID.setText(nameIdSubject);
            OMElement conditions =
                factory.createOMElement("Conditions", saml, assertion);
            conditions.addAttribute("NotBefore", strCurrentDate, null);
            conditions.addAttribute("NotOnOrAfter", strExpireDate, null);

            OMElement authnStatement =
                factory.createOMElement("AuthnStatement", saml, assertion);
            authnStatement.addAttribute("AuthnInstant",
                                        artifactRequest.getIssueInstant(),
                                        null);

            OMElement authnContext =
                factory.createOMElement("AuthnContext", saml, authnStatement);

            OMElement authnContextClassRef =
                factory.createOMElement("AuthnContextClassRef", saml,
                                        authnContext);
            authnContextClassRef.setText("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport");
        }

        soapEnvelope.serializeAndConsume(writer);
    }

    /**
     * Gets the user's Distinguished Name (DN)
     *
     * @param userName user name
     * @param rdnAttr relative DN LDAP attribute
     * @param ldapBaseuser LDAP base user entry
     *
     * @return the user's DN
     */
    public String getUsername(String userName, String rdnAttr,
                              String ldapBaseuser) {
        String userDN = null;
        try {
            userDN = rdnAttr + "=" + userName + "," + ldapBaseuser;
        } catch (Exception ex) {
            logger.error("Problem getting the DN");
        } finally {
        }
        return userDN;
    }

    /**
     * Checks the Object is not null
     *
     * @param object the object instance
     */
    public static final void checkNotNull(final Object object) {
        if (object == null) {
            throw new NullPointerException();
        }
    }

    /**
     * Reads the saml timeout defined in the config file
     *
     * @return saml timeout
     */
    public long getSamlTimeout() {

        if (samlTimeout == null) {

            ValveConfiguration valveConfig = getValveConfig();

            if (valveConfig != null) {
                samlTimeout =
                        new Long(valveConfig.getSAMLConfig().getSamlTimeout()).longValue();
                if (samlTimeout < 0) {
                    samlTimeout = Long.MAX_VALUE;
                }
            }
        }
        return samlTimeout.longValue();
    }

    /**
     * Gets the Valve configuration instance
     *
     * @return valve configuration
     */
    public ValveConfiguration getValveConfig() {

        ValveConfiguration valveConfig = null;

        try {
            valveConfig = ValveConfigurationInstance.getValveConfig();
        } catch (ValveConfigurationException e) {
            logger.error("Configuration Exception when getting Valve Config: " +
                         e);
        }

        return valveConfig;
    }

    /**
     * This inner class implements an artifact request that is stored in the
     * artifact vector, to get all the references there and securely consume
     * them
     *
     */
    private static final class ArtifactRequest {
        /**
         * Holds value of property id.
         */
        private String id;

        /**
         * Holds value of property artifact.
         */
        private String artifact;

        /**
         * Holds value of property issueInstant
         */
        private String issueInstant;

        /**
         * Class constructor - default
         *
         */
        public ArtifactRequest() {
        }

        /**
         * Class constructor
         *
         * @param id artifact id
         * @param artifact artifact
         * @param issueInstant timestamp
         */
        public ArtifactRequest(String id, String artifact,
                               String issueInstant) {
            this.id = id;
            this.artifact = artifact;
            this.issueInstant = issueInstant;
        }

        /**
         * Gets the artifact.
         *
         * @return artifact.
         */
        public String getArtifact() {
            return this.artifact;
        }

        /**
         * Sets the artifact.
         * @param artifact artifact vulue
         */
        public void setArtifact(String artifact) {
            this.artifact = artifact;
        }

        /**
         * Gets the artifact id.
         * @return artifact id
         */
        public String getId() {
            return this.id;
        }

        /**
         * Sets the artifact id
         * @param id artifact id
         */
        public void setId(String id) {
            this.id = id;
        }

        /**
         * Gets the issueInstant
         * @return issueInstant
         */
        public String getIssueInstant() {
            return this.issueInstant;
        }

        /**
         * Sets the issueInstant.
         * @param issueInstant timestamp
         */
        public void setIssueInstant(String issueInstant) {
            this.issueInstant = issueInstant;
        }
    }

}
TOP

Related Classes of com.google.gsa.valve.saml.authn.SAMLAuthNResolve$ArtifactRequest

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.