1 //%/////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
13 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //==============================================================================
24 // Author: Nag Boranna, Hewlett-Packard Company(nagaraja_boranna@hp.com)
28 //%/////////////////////////////////////////////////////////////////////////////
30 #include <Pegasus/Common/Constants.h>
31 #include <Pegasus/Common/HTTPAcceptor.h>
32 #include <Pegasus/Common/HTTPConnection.h>
33 #include <Pegasus/Common/HTTPMessage.h>
34 #include <Pegasus/Common/XmlWriter.h>
35 #include <Pegasus/Config/ConfigManager.h>
36 #include "HTTPAuthenticatorDelegator.h"
41 PEGASUS_NAMESPACE_BEGIN
45 HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator(
46 Uint32 operationMessageQueueId,
47 Uint32 exportMessageQueueId)
48 : Base(PEGASUS_QUEUENAME_HTTPAUTHDELEGATOR,
49 MessageQueue::getNextQueueId()),
50 _operationMessageQueueId(operationMessageQueueId),
51 _exportMessageQueueId(exportMessageQueueId)
53 PEG_METHOD_ENTER(TRC_HTTP,
54 "HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator");
56 _authenticationManager = new AuthenticationManager();
61 HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator()
63 PEG_METHOD_ENTER(TRC_HTTP,
64 "HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator");
66 delete _authenticationManager;
71 void HTTPAuthenticatorDelegator::_sendResponse(
73 Array<Sint8>& message)
75 PEG_METHOD_ENTER(TRC_HTTP,
76 "HTTPAuthenticatorDelegator::_sendResponse");
78 MessageQueue* queue = MessageQueue::lookup(queueId);
82 HTTPMessage* httpMessage = new HTTPMessage(message);
83 httpMessage->dest = queue->getQueueId();
85 queue->enqueue(httpMessage);
91 void HTTPAuthenticatorDelegator::_sendChallenge(
93 const String& authResponse)
95 PEG_METHOD_ENTER(TRC_HTTP,
96 "HTTPAuthenticatorDelegator::_sendChallenge");
99 // build unauthorized (401) response message
102 Array<Sint8> message;
103 XmlWriter::appendUnauthorizedResponseHeader(message, authResponse);
105 _sendResponse(queueId, message);
111 void HTTPAuthenticatorDelegator::_sendError(
113 const String errorMessage)
115 PEG_METHOD_ENTER(TRC_HTTP,
116 "HTTPAuthenticatorDelegator::_sendError");
119 // build error response message
122 Array<Sint8> message;
124 //ATTN: Need an ErrorResponseHeader() in XmlWriter
126 //message = XmlWriter::formatErrorResponseHeader(errorMessage);
128 _sendResponse(queueId, message);
134 void HTTPAuthenticatorDelegator::handleEnqueue(Message *message)
136 PEG_METHOD_ENTER(TRC_HTTP,
137 "HTTPAuthenticatorDelegator::handleEnqueue");
145 // Flag indicating whether the message should be deleted after handling.
146 // This should be set to false by handleHTTPMessage when the message is
147 // passed as is to another queue.
148 Boolean deleteMessage = true;
150 if (message->getType() == HTTP_MESSAGE)
152 handleHTTPMessage((HTTPMessage*)message, deleteMessage);
163 void HTTPAuthenticatorDelegator::handleEnqueue()
165 PEG_METHOD_ENTER(TRC_HTTP,
166 "HTTPAuthenticatorDelegator::handleEnqueue");
168 Message* message = dequeue();
170 handleEnqueue(message);
175 void HTTPAuthenticatorDelegator::handleHTTPMessage(
176 HTTPMessage* httpMessage,
177 Boolean & deleteMessage)
179 PEG_METHOD_ENTER(TRC_HTTP,
180 "HTTPAuthenticatorDelegator::handleHTTPMessage");
182 Boolean authenticated = false;
183 deleteMessage = true;
185 // ATTN-RK-P3-20020408: This check probably shouldn't be necessary, but
186 // we're getting an empty message when the client closes the connection
187 if (httpMessage->message.size() == 0)
189 // The message is empty; just drop it
194 // get the configured authentication flag
196 ConfigManager* configManager = ConfigManager::getInstance();
198 Boolean requireAuthentication = false;
201 configManager->getCurrentValue("requireAuthentication"), "true"))
203 requireAuthentication = true;
209 Uint32 queueId = httpMessage->queueId;
212 // Parse the HTTP message:
215 Array<HTTPHeader> headers;
216 Uint32 contentLength;
218 httpMessage->parse(startLine, headers, contentLength);
221 // Parse the request line:
227 HTTPMessage::parseRequestLine(
228 startLine, methodName, requestUri, httpVersion);
230 if (methodName != "M-POST" && methodName != "POST")
232 // Only POST and M-POST are implemented by this server
233 Array<Sint8> message;
234 message = XmlWriter::formatHttpErrorRspMessage(
235 HTTP_STATUS_NOTIMPLEMENTED);
236 _sendResponse(queueId, message);
241 // Process M-POST and POST messages:
244 httpMessage->message.append('\0');
247 // Search for Authorization header:
249 String authorization = String::EMPTY;
251 if ( HTTPMessage::lookupHeader(
252 headers, "PegasusAuthorization", authorization, false) &&
253 requireAuthentication
257 // Do pegasus/local authentication
260 _authenticationManager->performPegasusAuthentication(
262 httpMessage->authInfo);
266 String authChallenge = String::EMPTY;
267 String authResp = String::EMPTY;
269 authResp = _authenticationManager->getPegasusAuthResponseHeader(
271 httpMessage->authInfo);
273 if (!String::equal(authResp, String::EMPTY))
275 _sendChallenge(queueId, authResp);
279 _sendError(queueId, "Invalid Request");
287 if ( HTTPMessage::lookupHeader(
288 headers, "Authorization", authorization, false) &&
289 requireAuthentication
293 // Do http authentication if not authenticated already
298 _authenticationManager->performHttpAuthentication(
300 httpMessage->authInfo);
304 //ATTN: the number of challenges get sent for a
305 // request on a connection can be pre-set.
308 _authenticationManager->getHttpAuthResponseHeader();
310 if (!String::equal(authResp, String::EMPTY))
312 _sendChallenge(queueId, authResp);
316 _sendError(queueId, "Invalid Request");
325 if ( authenticated || !requireAuthentication )
328 // Search for "CIMOperation" header:
332 if (HTTPMessage::lookupHeader(
333 headers, "*CIMOperation", cimOperation, true))
335 MessageQueue* queue =
336 MessageQueue::lookup(_operationMessageQueueId);
340 httpMessage->dest = queue->getQueueId();
342 queue->enqueue(httpMessage);
343 deleteMessage = false;
346 else if (HTTPMessage::lookupHeader(
347 headers, "*CIMExport", cimOperation, true))
349 MessageQueue* queue =
350 MessageQueue::lookup(_exportMessageQueueId);
354 httpMessage->dest = queue->getQueueId();
356 queue->enqueue(httpMessage);
357 deleteMessage = false;
362 // We don't recognize this request message type
364 // The Specification for CIM Operations over HTTP reads:
366 // 3.3.4. CIMOperation
368 // If a CIM Server receives a CIM Operation request without
369 // this [CIMOperation] header, it MUST NOT process it as if
370 // it were a CIM Operation Request. The status code
371 // returned by the CIM Server in response to such a request
372 // is outside of the scope of this specification.
376 // If a CIM Listener receives a CIM Export request without
377 // this [CIMExport] header, it MUST NOT process it. The
378 // status code returned by the CIM Listener in response to
379 // such a request is outside of the scope of this
382 // The author has chosen to send a 400 Bad Request error, but
383 // without the CIMError header since this request must not be
384 // processed as a CIM request.
386 Array<Sint8> message;
387 message = XmlWriter::formatHttpErrorRspMessage(
388 HTTP_STATUS_BADREQUEST);
389 _sendResponse(queueId, message);
397 _authenticationManager->getHttpAuthResponseHeader();
399 if (!String::equal(authResp, String::EMPTY))
401 _sendChallenge(queueId, authResp);
405 _sendError(queueId, "Invalid Request");
413 PEGASUS_NAMESPACE_END