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

  1 karl  1.62 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.42 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.27 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.42 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.47 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.62 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 kumpf 1.18 // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20            // 
 21 kumpf 1.18 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24 kumpf 1.18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27 sushma.fernandes 1.60 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28 mike             1.2  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29                       //
 30                       //==============================================================================
 31                       //
 32                       // Author:  Nag Boranna,   Hewlett-Packard Company(nagaraja_boranna@hp.com)
 33                       //
 34 david            1.20 // Modified By: Dave Rosckes (rosckes@us.ibm.com)
 35 kumpf            1.28 //              Sushma Fernandes (sushma_fernandes@hp.com)
 36 h.sterling       1.34 //              Heather Sterling, IBM (hsterl@us.ibm.com)
 37 david.dillard    1.46 //              Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
 38                       //              David Dillard, VERITAS Software Corp.
 39                       //                  (david.dillard@veritas.com)
 40 j.alex           1.52 //              John Alex, IBM (johnalex@us.ibm.com) - Bug#2290
 41 mike             1.2  //
 42                       //%/////////////////////////////////////////////////////////////////////////////
 43                       
 44 kumpf            1.10 #include <Pegasus/Common/Constants.h>
 45 mike             1.2  #include <Pegasus/Common/HTTPAcceptor.h>
 46                       #include <Pegasus/Common/HTTPConnection.h>
 47                       #include <Pegasus/Common/HTTPMessage.h>
 48                       #include <Pegasus/Common/XmlWriter.h>
 49                       #include <Pegasus/Config/ConfigManager.h>
 50 humberto         1.33 #include <Pegasus/Common/Thread.h>
 51 mike             1.2  #include "HTTPAuthenticatorDelegator.h"
 52 humberto         1.33 #include <Pegasus/Common/MessageLoader.h>
 53 h.sterling       1.43 #include <Pegasus/Common/FileSystem.h>
 54 kumpf            1.58 #include <Pegasus/Common/LanguageParser.h>
 55 mday             1.17  
 56 gerarda          1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
 57                       #include <Pegasus/Common/CIMKerberosSecurityAssociation.h>
 58                       #endif 
 59 mike             1.2  
 60                       PEGASUS_USING_STD;
 61                       
 62                       PEGASUS_NAMESPACE_BEGIN
 63                       
 64 mike             1.56 static const String _HTTP_VERSION_1_0 = "HTTP/1.0";
 65                       
 66                       static const String _HTTP_METHOD_MPOST = "M-POST";
 67                       static const String _HTTP_METHOD = "POST";
 68                       
 69                       static const String _HTTP_HEADER_CIMEXPORT = "CIMExport";
 70                       static const String _HTTP_HEADER_CONNECTION = "Connection";
 71                       static const String _HTTP_HEADER_CIMOPERATION = "CIMOperation";
 72                       static const String _HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language";
 73                       static const String _HTTP_HEADER_CONTENT_LANGUAGE = "Content-Language";
 74                       static const String _HTTP_HEADER_AUTHORIZATION = "Authorization";
 75                       static const String _HTTP_HEADER_PEGASUSAUTHORIZATION = "PegasusAuthorization";
 76                       
 77                       static const String _CONFIG_PARAM_ENABLEAUTHENTICATION = "enableAuthentication";
 78                       
 79 mike             1.2  HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator(
 80                           Uint32 operationMessageQueueId,
 81 h.sterling       1.43     Uint32 exportMessageQueueId,
 82                       	CIMRepository* repository)
 83 kumpf            1.14    : Base(PEGASUS_QUEUENAME_HTTPAUTHDELEGATOR,
 84 kumpf            1.10           MessageQueue::getNextQueueId()),
 85 mike             1.2      _operationMessageQueueId(operationMessageQueueId),
 86 h.sterling       1.43     _exportMessageQueueId(exportMessageQueueId),
 87                       	_repository(repository)
 88 mike             1.2  {
 89 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
 90                               "HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator");
 91                       
 92 a.arora          1.36     _authenticationManager.reset(new AuthenticationManager());
 93 kumpf            1.11 
 94                           PEG_METHOD_EXIT();
 95 mike             1.2  }
 96                       
 97                       HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator()
 98                       {
 99 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
100                               "HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator");
101                       
102                           PEG_METHOD_EXIT();
103 mike             1.2  }
104                       
105 kumpf            1.48 void HTTPAuthenticatorDelegator::enqueue(Message* message)
106 kumpf            1.24 {
107                           handleEnqueue(message);
108                       }
109                       
110 mike             1.2  void HTTPAuthenticatorDelegator::_sendResponse(
111                           Uint32 queueId,
112 mike             1.54     Buffer& message,
113 j.alex           1.52     Boolean closeConnect)
114 mike             1.2  {
115 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
116                               "HTTPAuthenticatorDelegator::_sendResponse");
117                       
118 mike             1.2      MessageQueue* queue = MessageQueue::lookup(queueId);
119                       
120                           if (queue)
121                           {
122                               HTTPMessage* httpMessage = new HTTPMessage(message);
123 mday             1.6  	httpMessage->dest = queue->getQueueId();
124 j.alex           1.52     
125                               httpMessage->setCloseConnect(closeConnect);
126 kumpf            1.24 
127 mike             1.2          queue->enqueue(httpMessage);
128                           }
129 kumpf            1.11 
130                           PEG_METHOD_EXIT();
131 mike             1.2  }
132                       
133 gerarda          1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
134                       void HTTPAuthenticatorDelegator::_sendSuccess(
135                           Uint32 queueId,
136 j.alex           1.52     const String& authResponse,
137                           Boolean closeConnect)
138 gerarda          1.22 {
139                           PEG_METHOD_ENTER(TRC_HTTP,
140                               "HTTPAuthenticatorDelegator::_sendSuccess");
141                       
142                           //
143                           // build OK (200) response message
144                           //
145                       
146 mike             1.54     Buffer message;
147 gerarda          1.22     XmlWriter::appendOKResponseHeader(message, authResponse);
148                       
149 j.alex           1.52     _sendResponse(queueId, message,closeConnect);
150 gerarda          1.22 
151                           PEG_METHOD_EXIT();
152                       }
153                       #endif
154                       
155 mike             1.2  void HTTPAuthenticatorDelegator::_sendChallenge(
156                           Uint32 queueId,
157 j.alex           1.52     const String& authResponse,
158                           Boolean closeConnect)
159 mike             1.2  {
160 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
161                               "HTTPAuthenticatorDelegator::_sendChallenge");
162                       
163 mike             1.2      //
164                           // build unauthorized (401) response message
165                           //
166                       
167 mike             1.54     Buffer message;
168 kumpf            1.7      XmlWriter::appendUnauthorizedResponseHeader(message, authResponse);
169 mike             1.2  
170 j.alex           1.52     _sendResponse(queueId, message,closeConnect);
171 kumpf            1.11 
172                           PEG_METHOD_EXIT();
173 mike             1.2  }
174                       
175                       
176 kumpf            1.30 void HTTPAuthenticatorDelegator::_sendHttpError(
177 mike             1.2      Uint32 queueId,
178 kumpf            1.30     const String& status,
179                           const String& cimError,
180 j.alex           1.52     const String& pegasusError,
181                           Boolean closeConnect)
182 mike             1.2  {
183 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
184 kumpf            1.30         "HTTPAuthenticatorDelegator::_sendHttpError");
185 kumpf            1.11 
186 mike             1.2      //
187 kumpf            1.11     // build error response message
188 mike             1.2      //
189                       
190 mike             1.54     Buffer message;
191 kumpf            1.30     message = XmlWriter::formatHttpErrorRspMessage(
192                               status,
193                               cimError,
194                               pegasusError);
195 mike             1.2  
196 j.alex           1.52     _sendResponse(queueId, message,closeConnect);
197 kumpf            1.11 
198                           PEG_METHOD_EXIT();
199 mike             1.2  }
200                       
201 mday             1.5  
202                       void HTTPAuthenticatorDelegator::handleEnqueue(Message *message)
203 mike             1.2  {
204 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
205                               "HTTPAuthenticatorDelegator::handleEnqueue");
206 mike             1.2  
207 kumpf            1.11     if (!message)
208                           {
209                               PEG_METHOD_EXIT();
210 mike             1.2          return;
211 kumpf            1.11     }
212 mike             1.2  
213 kumpf            1.11     // Flag indicating whether the message should be deleted after handling.
214                           // This should be set to false by handleHTTPMessage when the message is
215                           // passed as is to another queue.
216                           Boolean deleteMessage = true;
217 mday             1.5     
218 mike             1.2      if (message->getType() == HTTP_MESSAGE)
219                           {
220                               handleHTTPMessage((HTTPMessage*)message, deleteMessage);
221                           }
222                       
223                           if (deleteMessage)
224                           {
225 j.alex           1.52         PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3,
226                                           "Deleting Message in HTTPAuthenticator::handleEnqueue");
227                       
228 mike             1.2          delete message;
229                           }
230 kumpf            1.11 
231                           PEG_METHOD_EXIT();
232 mday             1.5  }
233                       
234                       void HTTPAuthenticatorDelegator::handleEnqueue()
235                       {
236 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
237                               "HTTPAuthenticatorDelegator::handleEnqueue");
238                       
239 mday             1.5      Message* message = dequeue();
240                           if(message)
241                              handleEnqueue(message);
242 kumpf            1.11 
243                           PEG_METHOD_EXIT();
244 mike             1.2  }
245                       
246                       void HTTPAuthenticatorDelegator::handleHTTPMessage(
247                           HTTPMessage* httpMessage,
248                           Boolean & deleteMessage)
249                       {  
250 kumpf            1.11     PEG_METHOD_ENTER(TRC_HTTP,
251                               "HTTPAuthenticatorDelegator::handleHTTPMessage");
252                       
253 mike             1.2      deleteMessage = true;
254                       
255 kumpf            1.13     // ATTN-RK-P3-20020408: This check probably shouldn't be necessary, but
256                           // we're getting an empty message when the client closes the connection
257                           if (httpMessage->message.size() == 0)
258                           {
259                               // The message is empty; just drop it
260 gerarda          1.23         PEG_METHOD_EXIT();
261 kumpf            1.13         return;
262                           }
263                       
264 mike             1.2      //
265                           // Save queueId:
266                           //
267                           Uint32 queueId = httpMessage->queueId;
268                       
269                           //
270                           // Parse the HTTP message:
271                           //
272                           String startLine;
273                           Array<HTTPHeader> headers;
274                           Uint32 contentLength;
275 j.alex           1.52     String connectClose;
276                           Boolean closeConnect = false;
277 mike             1.2  
278                           httpMessage->parse(startLine, headers, contentLength);
279 j.alex           1.52     
280                           //
281                           // Check for Connection: Close
282                           //
283 mike             1.56     if(HTTPMessage::lookupHeader(
284                       	headers, _HTTP_HEADER_CONNECTION, connectClose, false))
285 j.alex           1.52     {
286                              if (String::equalNoCase(connectClose, "Close"))
287                              {
288                                   PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3,
289                                           "Header in HTTP Message Contains a Connection: Close");
290                                   closeConnect = true;
291                                   httpMessage->setCloseConnect(closeConnect);
292                              }
293                           }
294                       
295 kumpf            1.35     //
296 h.sterling       1.34     // Handle authentication:
297                           //
298                           ConfigManager* configManager = ConfigManager::getInstance();
299                           Boolean enableAuthentication = false;
300                           Boolean authenticated = false;
301                       
302 david            1.57 #ifdef PEGASUS_KERBEROS_AUTHENTICATION   
303                           CIMKerberosSecurityAssociation *sa = NULL; 
304                       	// The presence of a Security Association indicates that Kerberos is being used
305                       	// Reset flag for subsequent calls to indicate that no Authorization
306                               // record was sent. If one was sent the flag will be appropriately reset later.
307                       	// The sa is maintained while the connection is active.
308                               sa = httpMessage->authInfo->getSecurityAssociation();   
309                               if (sa)   
310                               {   
311                                   sa->setClientSentAuthorization(false);   
312                               }   
313                       #endif   	
314                       
315                       
316 kumpf            1.65     if (ConfigManager::parseBooleanValue(
317                               configManager->getCurrentValue(_CONFIG_PARAM_ENABLEAUTHENTICATION)))
318 h.sterling       1.34     {
319                               enableAuthentication = true;
320 kumpf            1.63 #ifdef PEGASUS_KERBEROS_AUTHENTICATION 
321 david            1.57         // 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.
322                               String authstr = String::EMPTY;  
323                               if (sa && sa->getClientAuthenticated() &&
324                                   !HTTPMessage::lookupHeader(headers, "Authorization", authstr, false)) 
325                               { 
326                                 authenticated = true; 
327                               } 
328                               if (!sa)
329                               { 
330                                 authenticated = httpMessage->authInfo->isAuthenticated();
331                               } 
332                       #else 
333 h.sterling       1.34         // Client may have already authenticated via SSL.
334                               // In this case, no further attempts to authenticate the client are made
335                               authenticated = httpMessage->authInfo->isAuthenticated();
336 david            1.57 #endif
337 kumpf            1.63 
338                               // Get the user name associated with the certificate (using the
339                               // certificate chain, if necessary).
340                       
341                               String certUserName;
342 h.sterling       1.34         if (authenticated && 
343 denise.eckstein  1.55             (String::equal(httpMessage->authInfo->getAuthType(),
344                                       AuthenticationInfoRep::AUTH_TYPE_SSL)))
345 h.sterling       1.34         {
346 kumpf            1.63             PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3, "Client was authenticated via trusted SSL certificate.");
347 h.sterling       1.43 
348 kumpf            1.63             String trustStore = configManager->getCurrentValue("sslTrustStore");
349 h.sterling       1.43 
350 kumpf            1.63             if (FileSystem::isDirectory(ConfigManager::getHomedPath(trustStore))) 
351                                   {
352 h.sterling       1.59                 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4, "Truststore is a directory, lookup username");
353 kumpf            1.63                
354 h.sterling       1.59                 //Get the client certificate chain to determine the correct username mapping.  
355                                       //Starting with the peer certificate, work your way up the chain
356                                       //towards the root certificate until a match is found in the repository.  
357                                       Array<SSLCertificateInfo*> clientCertificateChain = httpMessage->authInfo->getClientCertificateChain();
358                                       SSLCertificateInfo* clientCertificate = NULL;
359 h.sterling       1.43 
360 h.sterling       1.59                 Tracer::trace(TRC_HTTP, Tracer::LEVEL4, "Client certificate chain length: %d.", clientCertificateChain.size());
361                       
362 sushma.fernandes 1.60                 Uint32 loopCount = clientCertificateChain.size() - 1;
363                                       for (Uint32 i = 0; i <= loopCount ; i++)
364 h.sterling       1.59                 {
365                                           clientCertificate = clientCertificateChain[i];
366                                           if (clientCertificate == NULL)
367                                           {
368 kumpf            1.63                         MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.BAD_CERTIFICATE", 
369 h.sterling       1.59                                                     "The certificate used for authentication is not valid.");
370 kumpf            1.63                         String msg(MessageLoader::getMessage(msgParms));
371                                               _sendHttpError(
372                                                   queueId,
373                                                   HTTP_STATUS_UNAUTHORIZED,
374                                                   String::EMPTY,
375                                                   msg,
376                                                   closeConnect);
377                                               PEG_METHOD_EXIT();
378                                               return;
379 h.sterling       1.59                     }
380                                           PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4, "Certificate toString " + clientCertificate->toString());
381                       
382                                           //get certificate properties
383 kumpf            1.63                     String issuerName = clientCertificate->getIssuerName();
384                                           char serialNumber[256];
385                                           sprintf(serialNumber, "%lu", clientCertificate->getSerialNumber());
386 h.sterling       1.59     
387 sushma.fernandes 1.64                     //
388                                           // The truststore type key property is deprecated. To retain
389                                           // backward compatibility, add the truststore type property
390                                           // to the key bindings and set it to cimserver truststore.
391                                           //
392 kumpf            1.63         
393                                           //construct the corresponding PG_SSLCertificate instance
394                                           Array<CIMKeyBinding> keyBindings;
395                                           keyBindings.append(CIMKeyBinding("IssuerName", issuerName, CIMKeyBinding::STRING));
396                                           keyBindings.append(CIMKeyBinding("SerialNumber", serialNumber, CIMKeyBinding::STRING));
397 sushma.fernandes 1.64                     keyBindings.append(CIMKeyBinding("TruststoreType", 
398                                              PG_SSLCERTIFICATE_TSTYPE_VALUE_SERVER));
399 kumpf            1.63         
400                                           CIMObjectPath cimObjectPath("localhost",
401                                                                       PEGASUS_NAMESPACENAME_CERTIFICATE,
402                                                                       PEGASUS_CLASSNAME_CERTIFICATE,
403                                                                       keyBindings);
404 h.sterling       1.59 
405                                           PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4, "Client Certificate COP: " + cimObjectPath.toString());
406 kumpf            1.63                
407 h.sterling       1.59                     CIMInstance cimInstance;
408 kumpf            1.63                     CIMValue value;
409                                           Uint32 pos;
410                                           String userName = String::EMPTY;
411                               
412                                           //attempt to get the username registered to the certificate
413                                           try 
414                                           {
415                                               cimInstance = _repository->getInstance(PEGASUS_NAMESPACENAME_CERTIFICATE, cimObjectPath);
416 h.sterling       1.59 
417                                               pos = cimInstance.findProperty("RegisteredUserName");
418 kumpf            1.63                             
419                                               if (pos != PEG_NOT_FOUND && !(value = cimInstance.getProperty(pos).getValue()).isNull())
420 h.sterling       1.59                         {
421 kumpf            1.63                             value.get(userName);
422 h.sterling       1.59 
423 kumpf            1.63                             //
424                                                   // If a user name is specified, our search is complete
425                                                   //
426                                                   if (userName.size())
427                                                   {
428                                                       PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3,
429                                                           "User name for certificate is " + userName);
430                                                       certUserName = userName;
431                                                       break;
432                                                   }
433                       
434                                                   // No user name is specified; continue up the chain
435                                                   Tracer::trace(TRC_HTTP, Tracer::LEVEL4,
436                                                       "The certificate at level %u has no "
437                                                           "associated username, moving up the chain",
438                                                       i);
439                                               } 
440                                               else
441 h.sterling       1.59                         {
442 kumpf            1.63                             Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE,
443                                                   "HTTPAuthenticatorDelegator - Bailing, no username is registered to this certificate.");
444 h.sterling       1.59                         }
445 kumpf            1.63                     } catch (CIMException& e)
446                                           {
447 h.sterling       1.59                         //this certificate did not have a registration associated with it; continue up the chain
448                                               if (e.getCode() == CIM_ERR_NOT_FOUND)
449                                               {
450                                                   PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4, "No registration for this certificate, try next certificate in chain");
451                                                   continue;
452                       
453                                               } else
454                                               {
455 kumpf            1.63                             Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE,
456                                                               "HTTPAuthenticatorDelegator - Bailing, Bailing, the certificate used for authentication is not valid.");
457 h.sterling       1.59                             MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.BAD_CERTIFICATE",
458                                                                               "The certificate used for authentication is not valid.");
459 kumpf            1.63                             String msg(MessageLoader::getMessage(msgParms));
460 h.sterling       1.59                             PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3, msg);
461                                                                      _sendHttpError(
462                                                                           queueId,
463                                                                           HTTP_STATUS_UNAUTHORIZED,
464                                                                           String::EMPTY,
465                                                                           msg,
466                                                                           closeConnect);
467 kumpf            1.63                             PEG_METHOD_EXIT();
468                                                   return;
469 h.sterling       1.59                         }
470                           
471                                           } catch (...)
472                                           {
473                                               //this scenario can occur if a certificate cached on the server was deleted
474                                               //openssl would not pick up the deletion but we would pick it up here when we went to look it up
475                                               //in the repository
476 kumpf            1.63                         Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE,
477                                                           "HTTPAuthenticatorDelegator - Bailing, the certificate used for authentication is not valid.");
478 h.sterling       1.59                         MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.BAD_CERTIFICATE",
479                                                                           "The certificate used for authentication is not valid.");
480 kumpf            1.63                         String msg(MessageLoader::getMessage(msgParms));
481 h.sterling       1.59                         PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL3, msg);
482                                                                  _sendHttpError(
483                                                                       queueId,
484                                                                       HTTP_STATUS_UNAUTHORIZED,
485                                                                       String::EMPTY,
486                                                                       msg,
487                                                                       closeConnect);
488 kumpf            1.63                         PEG_METHOD_EXIT();
489                                               return;
490 h.sterling       1.59                     }
491                                       } //end for clientcertificatechain
492                                   } //end sslTrustStore directory
493                                   else
494 kumpf            1.63             {
495                                       //trustStore is a single CA file, lookup username
496                                       //user was already verified as a valid system user during server startup
497                                       certUserName =
498                                           configManager->getCurrentValue("sslTrustStoreUserName");
499                                   }
500                       
501                                   //
502                                   // Validate user information
503                                   //
504                       
505                                   if (!_authenticationManager->validateUserForHttpAuth(certUserName))
506                                   {
507                                       MessageLoaderParms msgParms(
508                                           "Pegasus.Server.HTTPAuthenticatorDelegator."
509                                               "BAD_CERTIFICATE_USERNAME",
510                                           "The username registered to this certificate is not a "
511                                               "valid user.");
512                                       _sendHttpError(
513                                           queueId,
514                                           HTTP_STATUS_UNAUTHORIZED,
515 kumpf            1.63                     String::EMPTY,
516                                           MessageLoader::getMessage(msgParms),
517                                           closeConnect);
518                                       PEG_METHOD_EXIT();
519                                       return;
520                                   }
521 h.sterling       1.44 
522 kumpf            1.63             httpMessage->authInfo->setAuthenticatedUser(certUserName);
523 h.sterling       1.43 
524 kumpf            1.63             PEG_TRACE_STRING(
525                                       TRC_HTTP,
526                                       Tracer::LEVEL3,
527                                       "User name for certificate is " + certUserName);
528                                   Logger::put(
529                                       Logger::STANDARD_LOG,
530                                       System::CIMSERVER,
531                                       Logger::TRACE,
532                                       "HTTPAuthenticatorDelegator - The trusted client certificate "
533                                           "is registered to $0.",
534                                       certUserName);
535                               }
536                           } //end enableAuthentication
537 h.sterling       1.43 
538 kumpf            1.63     PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL4, "Exited authentication loop");
539 h.sterling       1.43 
540 h.sterling       1.34 
541 humberto         1.33 // l10n start
542 kumpf            1.61    AcceptLanguageList acceptLanguages;
543                          ContentLanguageList contentLanguages;
544 humberto         1.33    try
545                          {
546                                       // Get and validate the Accept-Language header, if set
547                                       String acceptLanguageHeader;
548                                       if (HTTPMessage::lookupHeader(
549                                             headers,
550 mike             1.56 		      _HTTP_HEADER_ACCEPT_LANGUAGE,
551 humberto         1.33                       acceptLanguageHeader,
552                                         false) == true)
553                                   {
554 kumpf            1.58                 acceptLanguages = LanguageParser::parseAcceptLanguageHeader(
555                                           acceptLanguageHeader);
556                       		httpMessage->acceptLanguagesDecoded = true;
557 humberto         1.33             }
558                                                                                                                                                                                    
559                                       // Get and validate the Content-Language header, if set
560                                       String contentLanguageHeader;
561                                       if (HTTPMessage::lookupHeader(
562                                             headers,
563 mike             1.56                       _HTTP_HEADER_CONTENT_LANGUAGE,
564 humberto         1.33                       contentLanguageHeader,
565                                         false) == true)
566                                   {
567 kumpf            1.58                 contentLanguages = LanguageParser::parseContentLanguageHeader(
568                                           contentLanguageHeader);
569                       		httpMessage->contentLanguagesDecoded = true;
570 humberto         1.33             }
571                          }
572                          catch (Exception &e)
573                          {
574                       	Thread::clearLanguages(); // clear any existing languages to force messages to come from the root bundle
575                       	MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.REQUEST_NOT_VALID","request-not-valid");
576                       	String msg(MessageLoader::getMessage(msgParms));
577                       
578 j.alex           1.52         _sendHttpError(
579                                   queueId, 
580                                   HTTP_STATUS_BADREQUEST,
581                                   msg,
582                                   e.getMessage(),
583                                   closeConnect);
584 humberto         1.33         PEG_METHOD_EXIT();
585                               return;
586                          }
587 kumpf            1.61    Thread::setLanguages(new AcceptLanguageList(acceptLanguages));
588 humberto         1.33    httpMessage->acceptLanguages = acceptLanguages;
589                          httpMessage->contentLanguages = contentLanguages;
590                       // l10n end   
591                       
592                        
593 mike             1.2      //
594                           // Parse the request line:
595                           //
596                           String methodName;
597                           String requestUri;
598                           String httpVersion;
599 kumpf            1.19     HttpMethod httpMethod = HTTP_METHOD__POST;
600 mike             1.2  
601                           HTTPMessage::parseRequestLine(
602                               startLine, methodName, requestUri, httpVersion);
603                       
604 kumpf            1.19     //
605                           //  Set HTTP method for the request
606                           //
607 mike             1.56     if (methodName == _HTTP_METHOD_MPOST)
608 kumpf            1.19     {
609                               httpMethod = HTTP_METHOD_M_POST;
610                           }
611                       
612 mike             1.56     if (methodName != _HTTP_METHOD_MPOST && methodName != _HTTP_METHOD)
613 kumpf            1.11     {
614                               // Only POST and M-POST are implemented by this server
615 j.alex           1.52         _sendHttpError(
616                                   queueId,
617                                   HTTP_STATUS_NOTIMPLEMENTED,
618                                   String::EMPTY,
619                                   String::EMPTY,
620                                   closeConnect);
621 kumpf            1.19     }
622                           else if ((httpMethod == HTTP_METHOD_M_POST) &&
623 mike             1.56              (httpVersion == _HTTP_VERSION_1_0))
624 kumpf            1.19     {
625                               //
626                               //  M-POST method is not valid with version 1.0
627                               //
628 j.alex           1.52         _sendHttpError(
629                                   queueId,
630                                   HTTP_STATUS_BADREQUEST,
631                                   String::EMPTY,
632                                   String::EMPTY,
633                                   closeConnect);
634 kumpf            1.11     }
635                           else
636                           {
637                               //
638                               // Process M-POST and POST messages:
639                               //
640 mike             1.56 
641                       	PEG_LOGGER_TRACE((
642                       	    Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
643                       	    "HTTPAuthenticatorDelegator - M-POST/POST processing start"));
644 mike             1.2  
645                       	httpMessage->message.append('\0');
646                       
647 h.sterling       1.34     if (!authenticated && enableAuthentication) 
648                           {
649 mike             1.2          //
650                               // Search for Authorization header:
651                               //
652                               String authorization = String::EMPTY;
653                       
654 mike             1.56         if ( HTTPMessage::lookupHeader(headers, 
655                       	    _HTTP_HEADER_PEGASUSAUTHORIZATION, authorization, false) &&
656 kumpf            1.16              enableAuthentication
657 mike             1.2             )
658                               {
659 kumpf            1.28             try 
660                                   {
661                                       //
662                                       // Do pegasus/local authentication
663                                       //
664                                       authenticated = 
665                                           _authenticationManager->performPegasusAuthentication(
666                                               authorization,
667                                               httpMessage->authInfo);
668 mike             1.2  
669 kumpf            1.28                 if (!authenticated)
670                                       {
671                                           String authChallenge = String::EMPTY;
672                                           String authResp = String::EMPTY;
673 mike             1.2  
674 kumpf            1.28                     authResp = _authenticationManager->getPegasusAuthResponseHeader(
675                                               authorization,
676                                               httpMessage->authInfo);
677                       
678                                           if (!String::equal(authResp, String::EMPTY))
679                                           {
680 j.alex           1.52                         _sendChallenge(queueId, authResp,closeConnect);
681 kumpf            1.28                     }
682                                           else
683                                           {
684 humberto         1.33 			MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.AUTHORIZATION_HEADER_ERROR","Authorization header error");
685                       		        String msg(MessageLoader::getMessage(msgParms));
686 j.alex           1.52                         _sendHttpError(
687                                                   queueId,
688                                                   HTTP_STATUS_BADREQUEST,
689                                                   String::EMPTY,
690                                                   msg,
691                                                   closeConnect);
692 kumpf            1.28                     }
693 mike             1.2  
694 kumpf            1.28                     PEG_METHOD_EXIT();
695                                           return;
696 mike             1.2                  }
697 kumpf            1.28             }
698 david.dillard    1.41             catch (const CannotOpenFile &)
699 kumpf            1.28             {
700 j.alex           1.52                 _sendHttpError(
701                                           queueId,
702                                           HTTP_STATUS_INTERNALSERVERERROR,
703                                           String::EMPTY,
704                                           String::EMPTY,
705                                           closeConnect);
706 kumpf            1.11                 PEG_METHOD_EXIT();
707 mike             1.2                  return;
708 kumpf            1.28                 
709 mike             1.2              }
710                               }
711                       
712 david            1.57 
713 gerarda          1.31 
714 mike             1.2          if ( HTTPMessage::lookupHeader(
715 mike             1.56              headers, _HTTP_HEADER_AUTHORIZATION, authorization, false) &&
716 kumpf            1.16              enableAuthentication
717 mike             1.2             )
718                               {
719                                   //
720                                   // Do http authentication if not authenticated already
721                                   //
722                                   if (!authenticated)
723                                   {
724                                       authenticated =
725                                           _authenticationManager->performHttpAuthentication(
726                                               authorization,
727                                               httpMessage->authInfo);
728                       
729                                       if (!authenticated)
730                                       {
731                                           //ATTN: the number of challenges get sent for a 
732                                           //      request on a connection can be pre-set.
733 gerarda          1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
734                                           // Kerberos authentication needs access to the AuthenticationInfo
735                                           // object for this session in order to set up the reference to the
736                                           // CIMKerberosSecurityAssociation object for this session.
737 gerarda          1.23 
738 gerarda          1.22                     String authResp =   
739                                               _authenticationManager->getHttpAuthResponseHeader(httpMessage->authInfo);
740                       #else
741 mike             1.2                      String authResp =
742                                               _authenticationManager->getHttpAuthResponseHeader();
743 gerarda          1.22 #endif
744 kumpf            1.8                      if (!String::equal(authResp, String::EMPTY))
745                                           {
746 j.alex           1.52                         _sendChallenge(queueId, authResp,closeConnect);
747 kumpf            1.8                      }
748                                           else
749                                           {
750 humberto         1.33 			MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.AUTHORIZATION_HEADER_ERROR","Authorization header error");
751                                               String msg(MessageLoader::getMessage(msgParms));
752 j.alex           1.52                         _sendHttpError(
753                                                   queueId,
754                                                   HTTP_STATUS_BADREQUEST,
755                                                   String::EMPTY,
756                                                   msg,
757                                                   closeConnect);
758 kumpf            1.8                      }
759 mike             1.2  
760 kumpf            1.11                     PEG_METHOD_EXIT();
761 mike             1.2                      return;
762                                       }
763 gerarda          1.25 	    }  // first not authenticated check
764                       	}  // "Authorization" header check
765 david            1.57  } //end if(!authenticated && enableAuthentication)
766 gerarda          1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
767 gerarda          1.31 	// The pointer to the sa is created in the authenticator so we need to also
768                       	// assign it here.
769                       	sa = httpMessage->authInfo->getSecurityAssociation();
770                       	if (sa)
771 gerarda          1.26 	{
772 gerarda          1.31 	    Uint32 sendAction = 0;  // 0 - continue, 1 = send success, 2 = send response
773 gerarda          1.32 	    // The following is processing to unwrap (decrypt) the request from the
774                       	    // client when using kerberos authentication.
775 gerarda          1.31 	    sa->unwrapRequestMessage(httpMessage->message, contentLength,
776                       				     authenticated, sendAction);
777                       	    if (sendAction)  // send success or send response
778 gerarda          1.26 	    {
779 gerarda          1.31 		if (httpMessage->message.size() == 0)
780 gerarda          1.26 		{
781 humberto         1.33 			MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.AUTHORIZATION_HEADER_ERROR","Authorization header error");
782                                               String msg(MessageLoader::getMessage(msgParms));
783 j.alex           1.52                         _sendHttpError(
784                                                   queueId,
785                                                   HTTP_STATUS_BADREQUEST,
786                                                   String::EMPTY,
787                                                   msg,
788                                                   closeConnect);
789 gerarda          1.31 		}
790 gerarda          1.32 		else
791 gerarda          1.31 		{
792 gerarda          1.32 		    if (sendAction == 1)  // Send success
793                       		    {
794 j.alex           1.52                         _sendSuccess(
795                                                   queueId,
796                                                   String(
797                                                       httpMessage->message.getData(),httpMessage->message.size()), 
798                                                   closeConnect);
799 gerarda          1.32 		    }
800 gerarda          1.26 
801 gerarda          1.32 		    if (sendAction == 2)  // Send response
802                       		    {
803 j.alex           1.52 			_sendResponse(queueId, httpMessage->message,closeConnect);
804 gerarda          1.32 		    }
805 gerarda          1.31 		}
806 gerarda          1.25 
807                       		PEG_METHOD_EXIT();
808                       		return;
809                       	    }
810 gerarda          1.31 	}
811 gerarda          1.22 #endif
812 h.sterling       1.34 
813 david            1.57    
814 h.sterling       1.34 
815 mike             1.2  
816 kumpf            1.16         if ( authenticated || !enableAuthentication )
817 mike             1.2          {
818                                   //
819                                   // Search for "CIMOperation" header:
820                                   //
821                                   String cimOperation;
822                       
823                                   if (HTTPMessage::lookupHeader(
824 mike             1.56                 headers, _HTTP_HEADER_CIMOPERATION, cimOperation, true))
825 mike             1.2              {
826 mike             1.56 		PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
827                       			    "HTTPAuthenticatorDelegator - CIMOperation: $0 ",cimOperation));
828 david            1.21 
829 mike             1.2                  MessageQueue* queue =
830                                           MessageQueue::lookup(_operationMessageQueueId);
831                       
832                                       if (queue)
833                                       {
834 mday             1.6  		   httpMessage->dest = queue->getQueueId();
835                       		   
836 kumpf            1.29 		   try
837                       		     {
838                                              queue->enqueue(httpMessage);
839                       		     }
840 david.dillard    1.41 		   catch(const bad_alloc &)
841 kumpf            1.29 		     {
842                       		       delete httpMessage;
843 j.alex           1.52                        _sendHttpError(
844                                                  queueId,
845                                                  HTTP_STATUS_REQUEST_TOO_LARGE,
846                                                  String::EMPTY,
847                                                  String::EMPTY,
848                                                  closeConnect);
849 kumpf            1.29 		       PEG_METHOD_EXIT();
850                       		       deleteMessage = false;
851                       		       return;
852                       		     }
853                                        deleteMessage = false;
854 mike             1.2                  }
855                                   }
856                                   else if (HTTPMessage::lookupHeader(
857 mike             1.56                 headers, _HTTP_HEADER_CIMEXPORT, cimOperation, true))
858 mike             1.2              {
859 david            1.21 		Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
860                       			    "HTTPAuthenticatorDelegator - CIMExport: $0 ",cimOperation);
861                       
862 mike             1.2                  MessageQueue* queue =
863                                           MessageQueue::lookup(_exportMessageQueueId);
864                       
865                                       if (queue)
866                                       {
867 mday             1.6  		   httpMessage->dest = queue->getQueueId();
868                       
869                       		   queue->enqueue(httpMessage);
870                       		   deleteMessage = false;
871 mike             1.2                  }
872                                   }
873                                   else
874                                   {
875 kumpf            1.9                  // We don't recognize this request message type
876                       
877                                       // The Specification for CIM Operations over HTTP reads:
878                                       //
879                                       //     3.3.4. CIMOperation
880                                       //
881                                       //     If a CIM Server receives a CIM Operation request without
882                                       //     this [CIMOperation] header, it MUST NOT process it as if
883                                       //     it were a CIM Operation Request.  The status code
884                                       //     returned by the CIM Server in response to such a request
885                                       //     is outside of the scope of this specification.
886                                       //
887                                       //     3.3.5. CIMExport
888                                       //
889                                       //     If a CIM Listener receives a CIM Export request without
890                                       //     this [CIMExport] header, it MUST NOT process it.  The
891                                       //     status code returned by the CIM Listener in response to
892                                       //     such a request is outside of the scope of this
893                                       //     specification.
894                                       //
895                                       // The author has chosen to send a 400 Bad Request error, but
896 kumpf            1.9                  // without the CIMError header since this request must not be
897                                       // processed as a CIM request.
898                       
899 j.alex           1.52                 _sendHttpError(
900                                           queueId,
901                                           HTTP_STATUS_BADREQUEST,
902                                           String::EMPTY,
903                                           String::EMPTY,
904                                           closeConnect);
905 kumpf            1.11                 PEG_METHOD_EXIT();
906 mike             1.2                  return;
907 gerarda          1.25             } // bad request
908                               } // authenticated and enableAuthentication check
909 mike             1.2          else
910 gerarda          1.25         {  // client not authenticated; send challenge
911 gerarda          1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
912                                   String authResp =    
913                                       _authenticationManager->getHttpAuthResponseHeader(httpMessage->authInfo);
914                       #else
915 mike             1.2              String authResp =
916                                       _authenticationManager->getHttpAuthResponseHeader();
917 gerarda          1.22 #endif
918 mike             1.2  
919 kumpf            1.8              if (!String::equal(authResp, String::EMPTY))
920                                   {
921 j.alex           1.52                 _sendChallenge(queueId, authResp,closeConnect);
922 kumpf            1.8              }
923                                   else
924                                   {
925 humberto         1.33 		MessageLoaderParms msgParms("Pegasus.Server.HTTPAuthenticatorDelegator.AUTHORIZATION_HEADER_ERROR","Authorization header error");
926                                       String msg(MessageLoader::getMessage(msgParms));
927 j.alex           1.52                 _sendHttpError(
928                                           queueId,
929                                           HTTP_STATUS_BADREQUEST,
930                                           String::EMPTY,
931                                           msg,
932                                           closeConnect);
933 kumpf            1.8              }
934 mike             1.2          }
935 gerarda          1.25     } // M-POST and POST processing
936 kumpf            1.11 
937                           PEG_METHOD_EXIT();
938 mike             1.2  }
939                       
940                       PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2