(file) Return to HTTPAuthenticatorDelegator.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Server

File: [Pegasus] / pegasus / src / Pegasus / Server / HTTPAuthenticatorDelegator.cpp (download)
Revision: 1.69, Wed Feb 7 21:24:46 2007 UTC (17 years, 4 months ago) by sushma.fernandes
Branch: MAIN
CVS Tags: TASK-Bug2102_RCMPIWindows-root, TASK-Bug2102_RCMPIWindows-merged_out_to_branch, TASK-Bug2102_RCMPIWindows-merged_out_from_trunk, TASK-Bug2102_RCMPIWindows-merged_in_to_trunk, TASK-Bug2102_RCMPIWindows-merged_in_from_branch, TASK-Bug2102_RCMPIWindows-branch
Changes since 1.68: +19 -3 lines
BUG#: 6056
TITLE: Authorization failure messages should include username

DESCRIPTION: Updated the related messages to include username. Updated the tests.

//%2006////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation, The Open Group.
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; Symantec Corporation; The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
//%/////////////////////////////////////////////////////////////////////////////

#include <Pegasus/Common/Constants.h>
#include <Pegasus/Common/HTTPAcceptor.h>
#include <Pegasus/Common/HTTPConnection.h>
#include <Pegasus/Common/HTTPMessage.h>
#include <Pegasus/Common/XmlWriter.h>
#include <Pegasus/Config/ConfigManager.h>
#include <Pegasus/Common/Thread.h>
#include "HTTPAuthenticatorDelegator.h"
#include <Pegasus/Common/MessageLoader.h>
#include <Pegasus/Common/FileSystem.h>
#include <Pegasus/Common/LanguageParser.h>

#ifdef PEGASUS_KERBEROS_AUTHENTICATION
# include <Pegasus/Common/CIMKerberosSecurityAssociation.h>
#endif

PEGASUS_USING_STD;

PEGASUS_NAMESPACE_BEGIN

static const String _HTTP_VERSION_1_0 = "HTTP/1.0";

static const String _HTTP_METHOD_MPOST = "M-POST";
static const String _HTTP_METHOD = "POST";

static const String _HTTP_HEADER_CIMEXPORT = "CIMExport";
static const String _HTTP_HEADER_CONNECTION = "Connection";
static const String _HTTP_HEADER_CIMOPERATION = "CIMOperation";
static const String _HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language";
static const String _HTTP_HEADER_CONTENT_LANGUAGE = "Content-Language";
static const String _HTTP_HEADER_AUTHORIZATION = "Authorization";
static const String _HTTP_HEADER_PEGASUSAUTHORIZATION = "PegasusAuthorization";

static const String _CONFIG_PARAM_ENABLEAUTHENTICATION = "enableAuthentication";

HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator(
    Uint32 operationMessageQueueId,
    Uint32 exportMessageQueueId,
    CIMRepository* repository)
    : Base(PEGASUS_QUEUENAME_HTTPAUTHDELEGATOR, MessageQueue::getNextQueueId()),
      _operationMessageQueueId(operationMessageQueueId),
      _exportMessageQueueId(exportMessageQueueId),
      _repository(repository)
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator");

    _authenticationManager.reset(new AuthenticationManager());

    PEG_METHOD_EXIT();
}

HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator()
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator");

    PEG_METHOD_EXIT();
}

void HTTPAuthenticatorDelegator::enqueue(Message* message)
{
    handleEnqueue(message);
}

void HTTPAuthenticatorDelegator::_sendResponse(
    Uint32 queueId,
    Buffer& message,
    Boolean closeConnect)
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::_sendResponse");

    MessageQueue* queue = MessageQueue::lookup(queueId);

    if (queue)
    {
        HTTPMessage* httpMessage = new HTTPMessage(message);
        httpMessage->dest = queue->getQueueId();

        httpMessage->setCloseConnect(closeConnect);

        queue->enqueue(httpMessage);
    }

    PEG_METHOD_EXIT();
}

#ifdef PEGASUS_KERBEROS_AUTHENTICATION
void HTTPAuthenticatorDelegator::_sendSuccess(
    Uint32 queueId,
    const String& authResponse,
    Boolean closeConnect)
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::_sendSuccess");

    //
    // build OK (200) response message
    //

    Buffer message;
    XmlWriter::appendOKResponseHeader(message, authResponse);

    _sendResponse(queueId, message,closeConnect);

    PEG_METHOD_EXIT();
}
#endif

void HTTPAuthenticatorDelegator::_sendChallenge(
    Uint32 queueId,
    const String& authResponse,
    Boolean closeConnect)
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::_sendChallenge");

    //
    // build unauthorized (401) response message
    //

    Buffer message;
    XmlWriter::appendUnauthorizedResponseHeader(message, authResponse);

    _sendResponse(queueId, message,closeConnect);

    PEG_METHOD_EXIT();
}


void HTTPAuthenticatorDelegator::_sendHttpError(
    Uint32 queueId,
    const String& status,
    const String& cimError,
    const String& pegasusError,
    Boolean closeConnect)
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::_sendHttpError");

    //
    // build error response message
    //

    Buffer message;
    message = XmlWriter::formatHttpErrorRspMessage(
        status,
        cimError,
        pegasusError);

    _sendResponse(queueId, message,closeConnect);

    PEG_METHOD_EXIT();
}


void HTTPAuthenticatorDelegator::handleEnqueue(Message *message)
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::handleEnqueue");

    if (!message)
    {
        PEG_METHOD_EXIT();
        return;
    }

    // Flag indicating whether the message should be deleted after handling.
    // This should be set to false by handleHTTPMessage when the message is
    // passed as is to another queue.
    Boolean deleteMessage = true;

    if (message->getType() == HTTP_MESSAGE)
    {
        handleHTTPMessage((HTTPMessage*)message, deleteMessage);
    }

    if (deleteMessage)
    {
        PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3,
                    "Deleting Message in HTTPAuthenticator::handleEnqueue");

        delete message;
    }

    PEG_METHOD_EXIT();
}

void HTTPAuthenticatorDelegator::handleEnqueue()
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::handleEnqueue");

    Message* message = dequeue();
    if (message)
       handleEnqueue(message);

    PEG_METHOD_EXIT();
}

void HTTPAuthenticatorDelegator::handleHTTPMessage(
    HTTPMessage* httpMessage,
    Boolean& deleteMessage)
{
    PEG_METHOD_ENTER(TRC_HTTP,
        "HTTPAuthenticatorDelegator::handleHTTPMessage");

    deleteMessage = true;

    // ATTN-RK-P3-20020408: This check probably shouldn't be necessary, but
    // we're getting an empty message when the client closes the connection
    if (httpMessage->message.size() == 0)
    {
        // The message is empty; just drop it
        PEG_METHOD_EXIT();
        return;
    }

    //
    // Save queueId:
    //
    Uint32 queueId = httpMessage->queueId;

    //
    // Parse the HTTP message:
    //
    String startLine;
    Array<HTTPHeader> headers;
    Uint32 contentLength;
    String connectClose;
    Boolean closeConnect = false;

    httpMessage->parse(startLine, headers, contentLength);

    //
    // Check for Connection: Close
    //
    if (HTTPMessage::lookupHeader(
        headers, _HTTP_HEADER_CONNECTION, connectClose, false))
    {
        if (String::equalNoCase(connectClose, "Close"))
        {
            PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3,
                "Header in HTTP Message Contains a Connection: Close");
            closeConnect = true;
            httpMessage->setCloseConnect(closeConnect);
        }
    }

    //
    // Handle authentication:
    //
    ConfigManager* configManager = ConfigManager::getInstance();
    Boolean enableAuthentication = false;
    Boolean authenticated = false;

#ifdef PEGASUS_KERBEROS_AUTHENTICATION
    CIMKerberosSecurityAssociation* sa = NULL;
    // The presence of a Security Association indicates that Kerberos is
    // being used.
    // Reset flag for subsequent calls to indicate that no Authorization
    // record was sent. If one was sent the flag will be appropriately reset
    // later.
    // The sa is maintained while the connection is active.
    sa = httpMessage->authInfo->getSecurityAssociation();
    if (sa)
    {
        sa->setClientSentAuthorization(false);
    }
#endif

    if (ConfigManager::parseBooleanValue(configManager->getCurrentValue(
            _CONFIG_PARAM_ENABLEAUTHENTICATION)))
    {
        enableAuthentication = true;
#ifdef PEGASUS_KERBEROS_AUTHENTICATION
        // If we are using Kerberos (sa pointer is set), the client has
        // already authenticated, and the client is NOT attempting to
        // re-authenticate (dermined by an Authorization record being sent),
        // then we want to set the local authenticate flag to true so that
        // the authentication logic is skipped.
        String authstr;
        if (sa && sa->getClientAuthenticated() &&
            !HTTPMessage::lookupHeader(
                 headers, "Authorization", authstr, false))
        {
            authenticated = true;
        }

        if (!sa)
        {
            authenticated = httpMessage->authInfo->isAuthenticated();
        }
#else
        // Client may have already authenticated via SSL.
        // In this case, no further attempts to authenticate the client are made
        authenticated = httpMessage->authInfo->isAuthenticated();
#endif

        // Get the user name associated with the certificate (using the
        // certificate chain, if necessary).

        String certUserName;
        if (authenticated &&
            (String::equal(httpMessage->authInfo->getAuthType(),
                AuthenticationInfoRep::AUTH_TYPE_SSL)))
        {
            PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3,
                "Client was authenticated via trusted SSL certificate.");

            String trustStore = configManager->getCurrentValue("sslTrustStore");

            if (FileSystem::isDirectory(
                    ConfigManager::getHomedPath(trustStore)))
            {
                PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4,
                    "Truststore is a directory, lookup username");

                // Get the client certificate chain to determine the correct
                // username mapping.  Starting with the peer certificate,
                // work your way up the chain towards the root certificate
                // until a match is found in the repository.
                Array<SSLCertificateInfo*> clientCertificateChain =
                    httpMessage->authInfo->getClientCertificateChain();
                SSLCertificateInfo* clientCertificate = NULL;

                Tracer::trace(TRC_HTTP, Tracer::LEVEL4,
                    "Client certificate chain length: %d.",
                    clientCertificateChain.size());

                Uint32 loopCount = clientCertificateChain.size() - 1;
                for (Uint32 i = 0; i <= loopCount ; i++)
                {
                    clientCertificate = clientCertificateChain[i];
                    if (clientCertificate == NULL)
                    {
                        MessageLoaderParms msgParms(
                            "Pegasus.Server.HTTPAuthenticatorDelegator."
                                "BAD_CERTIFICATE",
                            "The certificate used for authentication is not "
                                "valid.");
                        String msg(MessageLoader::getMessage(msgParms));
                        _sendHttpError(
                            queueId,
                            HTTP_STATUS_UNAUTHORIZED,
                            String::EMPTY,
                            msg,
                            closeConnect);
                        PEG_METHOD_EXIT();
                        return;
                    }
                    PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4,
                        "Certificate toString " +
                            clientCertificate->toString());

                    //get certificate properties
                    String issuerName = clientCertificate->getIssuerName();
                    char serialNumber[256];
                    sprintf(serialNumber, "%lu",
                        clientCertificate->getSerialNumber());

                    //
                    // The truststore type key property is deprecated. To retain
                    // backward compatibility, add the truststore type property
                    // to the key bindings and set it to cimserver truststore.
                    //

                    //construct the corresponding PG_SSLCertificate instance
                    Array<CIMKeyBinding> keyBindings;
                    keyBindings.append(CIMKeyBinding(
                        "IssuerName", issuerName, CIMKeyBinding::STRING));
                    keyBindings.append(CIMKeyBinding(
                        "SerialNumber", serialNumber, CIMKeyBinding::STRING));
                    keyBindings.append(CIMKeyBinding("TruststoreType",
                        PG_SSLCERTIFICATE_TSTYPE_VALUE_SERVER));

                    CIMObjectPath cimObjectPath(
                        "localhost",
                        PEGASUS_NAMESPACENAME_CERTIFICATE,
                        PEGASUS_CLASSNAME_CERTIFICATE,
                        keyBindings);

                    PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4,
                        "Client Certificate COP: " + cimObjectPath.toString());

                    CIMInstance cimInstance;
                    CIMValue value;
                    Uint32 pos;
                    String userName = String::EMPTY;

                    //attempt to get the username registered to the certificate
                    try
                    {
                        cimInstance = _repository->getInstance(
                            PEGASUS_NAMESPACENAME_CERTIFICATE, cimObjectPath);

                        pos = cimInstance.findProperty("RegisteredUserName");

                        if (pos != PEG_NOT_FOUND &&
                            !(value = cimInstance.getProperty(pos).
                                  getValue()).isNull())
                        {
                            value.get(userName);

                            //
                            // If a user name is specified, our search is
                            // complete
                            //
                            if (userName.size())
                            {
                                PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3,
                                    "User name for certificate is " + userName);
                                certUserName = userName;
                                break;
                            }

                            // No user name is specified; continue up the chain
                            Tracer::trace(TRC_HTTP, Tracer::LEVEL4,
                                "The certificate at level %u has no "
                                    "associated username, moving up the chain",
                                i);
                        }
                        else
                        {
                            Logger::put(
                                Logger::ERROR_LOG,
                                System::CIMSERVER,
                                Logger::TRACE,
                                "HTTPAuthenticatorDelegator - Bailing, no "
                                    "username is registered to this "
                                    "certificate.");
                        }
                    }
                    catch (CIMException& e)
                    {
                        // this certificate did not have a registration
                        // associated with it; continue up the chain
                        if (e.getCode() == CIM_ERR_NOT_FOUND)
                        {
                            PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4,
                                "No registration for this certificate, try "
                                    "next certificate in chain");
                            continue;
                        }
                        else
                        {
                            Logger::put(
                                Logger::ERROR_LOG,
                                System::CIMSERVER,
                                Logger::TRACE,
                                "HTTPAuthenticatorDelegator - Bailing, "
                                    "the certificate used for authentication "
                                    "is not valid.");
                            MessageLoaderParms msgParms(
                                "Pegasus.Server.HTTPAuthenticatorDelegator."
                                    "BAD_CERTIFICATE",
                                "The certificate used for authentication is "
                                    "not valid.");
                            String msg(MessageLoader::getMessage(msgParms));
                            PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3, msg);
                            _sendHttpError(
                                queueId,
                                HTTP_STATUS_UNAUTHORIZED,
                                String::EMPTY,
                                msg,
                                closeConnect);
                            PEG_METHOD_EXIT();
                            return;
                        }
                    }
                    catch (...)
                    {
                        // this scenario can occur if a certificate cached
                        // on the server was deleted openssl would not pick
                        // up the deletion but we would pick it up here when
                        // we went to look it up in the repository
                        Logger::put(
                            Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE,
                            "HTTPAuthenticatorDelegator - Bailing, the "
                                "certificate used for authentication is not "
                                "valid.");
                        MessageLoaderParms msgParms(
                            "Pegasus.Server.HTTPAuthenticatorDelegator."
                                "BAD_CERTIFICATE",
                            "The certificate used for authentication is not "
                                "valid.");
                        String msg(MessageLoader::getMessage(msgParms));
                        PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3, msg);
                        _sendHttpError(
                            queueId,
                            HTTP_STATUS_UNAUTHORIZED,
                            String::EMPTY,
                            msg,
                            closeConnect);
                        PEG_METHOD_EXIT();
                        return;
                    }
                } //end for clientcertificatechain
            } //end sslTrustStore directory
            else
            {
                // trustStore is a single CA file, lookup username
                // user was already verified as a valid system user during
                // server startup
                certUserName =
                    configManager->getCurrentValue("sslTrustStoreUserName");
            }

            //
            // Validate user information
            //

            if (certUserName == String::EMPTY)
            {
                MessageLoaderParms msgParms(
                    "Pegasus.Server.HTTPAuthenticatorDelegator."
                        "BAD_CERTIFICATE_USERNAME",
                    "No username is registered to this certificate.");
                _sendHttpError(
                    queueId,
                    HTTP_STATUS_UNAUTHORIZED,
                    String::EMPTY,
                    MessageLoader::getMessage(msgParms),
                    closeConnect);
                PEG_METHOD_EXIT();
                return;
            }

            if (!_authenticationManager->validateUserForHttpAuth(certUserName))
            {
                MessageLoaderParms msgParms(
                    "Pegasus.Server.HTTPAuthenticatorDelegator."
                        "CERTIFICATE_USER_NOT_VALID",
                    "User '$0' registered to this certificate is not a "
                        "valid user.", certUserName);
                _sendHttpError(
                    queueId,
                    HTTP_STATUS_UNAUTHORIZED,
                    String::EMPTY,
                    MessageLoader::getMessage(msgParms),
                    closeConnect);
                PEG_METHOD_EXIT();
                return;
            }

            httpMessage->authInfo->setAuthenticatedUser(certUserName);

            PEG_TRACE_STRING(
                TRC_HTTP,
                Tracer::LEVEL3,
                "User name for certificate is " + certUserName);
            Logger::put(
                Logger::STANDARD_LOG,
                System::CIMSERVER,
                Logger::TRACE,
                "HTTPAuthenticatorDelegator - The trusted client certificate "
                    "is registered to $0.",
                certUserName);
        }
    } //end enableAuthentication

    PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4, "Exited authentication loop");

    AcceptLanguageList acceptLanguages;
    ContentLanguageList contentLanguages;
    try
    {
        // Get and validate the Accept-Language header, if set
        String acceptLanguageHeader;
        if (HTTPMessage::lookupHeader(
                headers,
                _HTTP_HEADER_ACCEPT_LANGUAGE,
                acceptLanguageHeader,
                false))
        {
            acceptLanguages = LanguageParser::parseAcceptLanguageHeader(
                acceptLanguageHeader);
            httpMessage->acceptLanguagesDecoded = true;
        }

        // Get and validate the Content-Language header, if set
        String contentLanguageHeader;
        if (HTTPMessage::lookupHeader(
                headers,
                _HTTP_HEADER_CONTENT_LANGUAGE,
                contentLanguageHeader,
                false))
        {
            contentLanguages = LanguageParser::parseContentLanguageHeader(
                contentLanguageHeader);
            httpMessage->contentLanguagesDecoded = true;
        }
    }
    catch (Exception& e)
    {
        // clear any existing languages to force messages to come from the
        // root bundle
        Thread::clearLanguages();
        MessageLoaderParms msgParms(
            "Pegasus.Server.HTTPAuthenticatorDelegator.REQUEST_NOT_VALID",
            "request-not-valid");
        String msg(MessageLoader::getMessage(msgParms));

        _sendHttpError(
            queueId,
            HTTP_STATUS_BADREQUEST,
            msg,
            e.getMessage(),
            closeConnect);
        PEG_METHOD_EXIT();
        return;
    }

    Thread::setLanguages(new AcceptLanguageList(acceptLanguages));
    httpMessage->acceptLanguages = acceptLanguages;
    httpMessage->contentLanguages = contentLanguages;

    //
    // Parse the request line:
    //
    String methodName;
    String requestUri;
    String httpVersion;
    HttpMethod httpMethod = HTTP_METHOD__POST;

    HTTPMessage::parseRequestLine(
        startLine, methodName, requestUri, httpVersion);

    //
    //  Set HTTP method for the request
    //
    if (methodName == _HTTP_METHOD_MPOST)
    {
        httpMethod = HTTP_METHOD_M_POST;
    }

    if (methodName != _HTTP_METHOD_MPOST && methodName != _HTTP_METHOD)
    {
        // Only POST and M-POST are implemented by this server
        _sendHttpError(
            queueId,
            HTTP_STATUS_NOTIMPLEMENTED,
            String::EMPTY,
            String::EMPTY,
            closeConnect);
    }
    else if ((httpMethod == HTTP_METHOD_M_POST) &&
             (httpVersion == _HTTP_VERSION_1_0))
    {
        //
        //  M-POST method is not valid with version 1.0
        //
        _sendHttpError(
            queueId,
            HTTP_STATUS_BADREQUEST,
            String::EMPTY,
            String::EMPTY,
            closeConnect);
    }
    else
    {
        //
        // Process M-POST and POST messages:
        //

        PEG_LOGGER_TRACE((
            Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
            "HTTPAuthenticatorDelegator - M-POST/POST processing start"));

        httpMessage->message.append('\0');

        if (!authenticated && enableAuthentication)
        {
            //
            // Search for Authorization header:
            //
            String authorization;

            if (HTTPMessage::lookupHeader(headers,
                    _HTTP_HEADER_PEGASUSAUTHORIZATION, authorization, false) &&
                enableAuthentication)
            {
                try
                {
                    //
                    // Do pegasus/local authentication
                    //
                    authenticated =
                        _authenticationManager->performPegasusAuthentication(
                            authorization,
                            httpMessage->authInfo);

                    if (!authenticated)
                    {
                        String authChallenge;
                        String authResp;

                        authResp = _authenticationManager->
                            getPegasusAuthResponseHeader(
                                authorization,
                                httpMessage->authInfo);

                        if (!String::equal(authResp, String::EMPTY))
                        {
                            _sendChallenge(queueId, authResp,closeConnect);
                        }
                        else
                        {
                            MessageLoaderParms msgParms(
                                "Pegasus.Server.HTTPAuthenticatorDelegator."
                                    "AUTHORIZATION_HEADER_ERROR",
                                "Authorization header error");
                            String msg(MessageLoader::getMessage(msgParms));
                            _sendHttpError(
                                queueId,
                                HTTP_STATUS_BADREQUEST,
                                String::EMPTY,
                                msg,
                                closeConnect);
                        }

                        PEG_METHOD_EXIT();
                        return;
                    }
                }
                catch (const CannotOpenFile&)
                {
                    _sendHttpError(
                        queueId,
                        HTTP_STATUS_INTERNALSERVERERROR,
                        String::EMPTY,
                        String::EMPTY,
                        closeConnect);
                    PEG_METHOD_EXIT();
                    return;
                }
            }

            if (HTTPMessage::lookupHeader(
                    headers, _HTTP_HEADER_AUTHORIZATION, authorization, false)
                && enableAuthentication)
            {
                //
                // Do http authentication if not authenticated already
                //
                if (!authenticated)
                {
                    authenticated =
                        _authenticationManager->performHttpAuthentication(
                            authorization,
                            httpMessage->authInfo);

                    if (!authenticated)
                    {
                        //ATTN: the number of challenges get sent for a
                        //      request on a connection can be pre-set.
#ifdef PEGASUS_KERBEROS_AUTHENTICATION
                        // Kerberos authentication needs access to the
                        // AuthenticationInfo object for this session in
                        // order to set up the reference to the
                        // CIMKerberosSecurityAssociation object for this
                        // session.

                        String authResp =
                            _authenticationManager->getHttpAuthResponseHeader(
                                httpMessage->authInfo);
#else
                        String authResp =
                            _authenticationManager->getHttpAuthResponseHeader();
#endif
                        if (!String::equal(authResp, String::EMPTY))
                        {
                            _sendChallenge(queueId, authResp,closeConnect);
                        }
                        else
                        {
                            MessageLoaderParms msgParms(
                                "Pegasus.Server.HTTPAuthenticatorDelegator."
                                    "AUTHORIZATION_HEADER_ERROR",
                                "Authorization header error");
                            String msg(MessageLoader::getMessage(msgParms));
                            _sendHttpError(
                                queueId,
                                HTTP_STATUS_BADREQUEST,
                                String::EMPTY,
                                msg,
                                closeConnect);
                        }

                        PEG_METHOD_EXIT();
                        return;
                    }
                }  // first not authenticated check
            }  // "Authorization" header check
        } //end if (!authenticated && enableAuthentication)

#ifdef PEGASUS_KERBEROS_AUTHENTICATION
        // The pointer to the sa is created in the authenticator so we need
        // to also assign it here.
        sa = httpMessage->authInfo->getSecurityAssociation();
        if (sa)
        {
            // 0 - continue, 1 = send success, 2 = send response
            Uint32 sendAction = 0;

            // The following is processing to unwrap (decrypt) the request
            // from the client when using kerberos authentication.
            sa->unwrapRequestMessage(
                httpMessage->message, contentLength, authenticated, sendAction);

            if (sendAction)  // send success or send response
            {
                if (httpMessage->message.size() == 0)
                {
                    MessageLoaderParms msgParms(
                        "Pegasus.Server.HTTPAuthenticatorDelegator."
                            "AUTHORIZATION_HEADER_ERROR",
                        "Authorization header error");
                    String msg(MessageLoader::getMessage(msgParms));
                    _sendHttpError(
                        queueId,
                        HTTP_STATUS_BADREQUEST,
                        String::EMPTY,
                        msg,
                        closeConnect);
                }
                else
                {
                    if (sendAction == 1)  // Send success
                    {
                        _sendSuccess(
                            queueId,
                            String(
                                httpMessage->message.getData(),
                                httpMessage->message.size()),
                            closeConnect);
                    }

                    if (sendAction == 2)  // Send response
                    {
                        _sendResponse(
                            queueId,
                            httpMessage->message,
                            closeConnect);
                    }
                }

                PEG_METHOD_EXIT();
                return;
            }
        }
#endif

        if (authenticated || !enableAuthentication)
        {
            // Final bastion to ensure the remote privileged user access
            // check is done as it should be
            // check for remote privileged User Access
            if (!httpMessage->authInfo->getRemotePrivilegedUserAccessChecked())
            {
                // the AuthenticationHandler did not process the
                // enableRemotePrivilegedUserAccess check
                // time to do it ourselves
                String userName = httpMessage->authInfo->getAuthenticatedUser();
                if (!AuthenticationManager::isRemotePrivilegedUserAccessAllowed(
                        userName))
                {
                    // Send client a message that we can't proceed to talk
                    // to him
                    // HTTP 401 ?
                    MessageLoaderParms msgParms(
                        "Server.CIMOperationRequestAuthorizer."
                            "REMOTE_NOT_ENABLED",
                        "Remote privileged user access is not enabled.");
                    String msg(MessageLoader::getMessage(msgParms));
                    _sendHttpError(
                        queueId,
                        HTTP_STATUS_UNAUTHORIZED,
                        String::EMPTY,
                        msg,
                        closeConnect);
                    PEG_METHOD_EXIT();
                    return;
                }
                httpMessage->authInfo->setRemotePrivilegedUserAccessChecked();
            }

            //
            // Search for "CIMOperation" header:
            //
            String cimOperation;

            if (HTTPMessage::lookupHeader(
                headers, _HTTP_HEADER_CIMOPERATION, cimOperation, true))
            {
                PEG_LOGGER_TRACE(
                    (Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
                     "HTTPAuthenticatorDelegator - CIMOperation: $0 ",
                     cimOperation));

                MessageQueue* queue =
                    MessageQueue::lookup(_operationMessageQueueId);

                if (queue)
                {
                    httpMessage->dest = queue->getQueueId();

                    try
                    {
                        queue->enqueue(httpMessage);
                    }
                    catch (const bad_alloc&)
                    {
                        delete httpMessage;
                        _sendHttpError(
                            queueId,
                            HTTP_STATUS_REQUEST_TOO_LARGE,
                            String::EMPTY,
                            String::EMPTY,
                            closeConnect);
                        PEG_METHOD_EXIT();
                        deleteMessage = false;
                        return;
                    }
                    deleteMessage = false;
                }
            }
            else if (HTTPMessage::lookupHeader(
                headers, _HTTP_HEADER_CIMEXPORT, cimOperation, true))
            {
                Logger::put(
                    Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
                    "HTTPAuthenticatorDelegator - CIMExport: $0 ",cimOperation);

                MessageQueue* queue =
                    MessageQueue::lookup(_exportMessageQueueId);

                if (queue)
                {
                    httpMessage->dest = queue->getQueueId();

                    queue->enqueue(httpMessage);
                    deleteMessage = false;
                }
            }
            else
            {
                // We don't recognize this request message type

                // The Specification for CIM Operations over HTTP reads:
                //
                //     3.3.4. CIMOperation
                //
                //     If a CIM Server receives a CIM Operation request without
                //     this [CIMOperation] header, it MUST NOT process it as if
                //     it were a CIM Operation Request.  The status code
                //     returned by the CIM Server in response to such a request
                //     is outside of the scope of this specification.
                //
                //     3.3.5. CIMExport
                //
                //     If a CIM Listener receives a CIM Export request without
                //     this [CIMExport] header, it MUST NOT process it.  The
                //     status code returned by the CIM Listener in response to
                //     such a request is outside of the scope of this
                //     specification.
                //
                // The author has chosen to send a 400 Bad Request error, but
                // without the CIMError header since this request must not be
                // processed as a CIM request.

                _sendHttpError(
                    queueId,
                    HTTP_STATUS_BADREQUEST,
                    String::EMPTY,
                    String::EMPTY,
                    closeConnect);
                PEG_METHOD_EXIT();
                return;
            } // bad request
        } // authenticated and enableAuthentication check
        else
        {  // client not authenticated; send challenge
#ifdef PEGASUS_KERBEROS_AUTHENTICATION
            String authResp =
                _authenticationManager->getHttpAuthResponseHeader(
                    httpMessage->authInfo);
#else
            String authResp =
                _authenticationManager->getHttpAuthResponseHeader();
#endif

            if (!String::equal(authResp, String::EMPTY))
            {
                _sendChallenge(queueId, authResp,closeConnect);
            }
            else
            {
                MessageLoaderParms msgParms(
                    "Pegasus.Server.HTTPAuthenticatorDelegator."
                        "AUTHORIZATION_HEADER_ERROR",
                    "Authorization header error");
                String msg(MessageLoader::getMessage(msgParms));
                _sendHttpError(
                    queueId,
                    HTTP_STATUS_BADREQUEST,
                    String::EMPTY,
                    msg,
                    closeConnect);
            }
        }
    } // M-POST and POST processing

    PEG_METHOD_EXIT();
}

PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2