1 martin 1.91 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.92 //
|
3 martin 1.91 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.92 //
|
10 martin 1.91 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.92 //
|
17 martin 1.91 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.92 //
|
20 martin 1.91 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.92 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.91 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.92 //
|
28 martin 1.91 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
|
32 sushma.fernandes 1.76 #include <Pegasus/Common/AuditLogger.h>
|
33 kumpf 1.10 #include <Pegasus/Common/Constants.h>
|
34 mike 1.2 #include <Pegasus/Common/HTTPAcceptor.h>
35 #include <Pegasus/Common/HTTPConnection.h>
36 #include <Pegasus/Common/HTTPMessage.h>
37 #include <Pegasus/Common/XmlWriter.h>
|
38 humberto 1.33 #include <Pegasus/Common/Thread.h>
39 #include <Pegasus/Common/MessageLoader.h>
|
40 h.sterling 1.43 #include <Pegasus/Common/FileSystem.h>
|
41 kumpf 1.58 #include <Pegasus/Common/LanguageParser.h>
|
42 kumpf 1.82 #include <Pegasus/Config/ConfigManager.h>
43 #include "HTTPAuthenticatorDelegator.h"
|
44 kumpf 1.68
|
45 gerarda 1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
|
46 kumpf 1.68 # include <Pegasus/Common/CIMKerberosSecurityAssociation.h>
47 #endif
|
48 mike 1.2
|
49 thilo.boehm 1.77 #ifdef PEGASUS_ZOS_SECURITY
50 // This include file will not be provided in the OpenGroup CVS for now.
51 // Do NOT try to include it in your compile
|
52 kumpf 1.82 # include <Pegasus/Common/safCheckzOS_inline.h>
|
53 thilo.boehm 1.77 #endif
54
55 #ifdef PEGASUS_OS_ZOS
|
56 kumpf 1.82 # include <sys/ps.h>
|
57 thilo.boehm 1.77 #endif
58
|
59 mike 1.2 PEGASUS_USING_STD;
60
61 PEGASUS_NAMESPACE_BEGIN
62
|
63 mike 1.56 static const String _HTTP_VERSION_1_0 = "HTTP/1.0";
64
65 static const String _HTTP_METHOD_MPOST = "M-POST";
66 static const String _HTTP_METHOD = "POST";
67
|
68 kumpf 1.94 static const char* _HTTP_HEADER_CIMEXPORT = "CIMExport";
69 static const char* _HTTP_HEADER_CONNECTION = "Connection";
70 static const char* _HTTP_HEADER_CIMOPERATION = "CIMOperation";
71 static const char* _HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language";
72 static const char* _HTTP_HEADER_CONTENT_LANGUAGE = "Content-Language";
73 static const char* _HTTP_HEADER_AUTHORIZATION = "Authorization";
74 static const char* _HTTP_HEADER_PEGASUSAUTHORIZATION = "PegasusAuthorization";
|
75 mike 1.56
76 static const String _CONFIG_PARAM_ENABLEAUTHENTICATION = "enableAuthentication";
77
|
78 mike 1.2 HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator(
|
79 kumpf 1.83 Uint32 cimOperationMessageQueueId,
80 Uint32 cimExportMessageQueueId,
|
81 kumpf 1.68 CIMRepository* repository)
|
82 sahana.prabhakar 1.95 : Base(PEGASUS_QUEUENAME_HTTPAUTHDELEGATOR),
|
83 kumpf 1.83 _cimOperationMessageQueueId(cimOperationMessageQueueId),
84 _cimExportMessageQueueId(cimExportMessageQueueId),
85 _wsmanOperationMessageQueueId(PEG_NOT_FOUND),
|
86 kumpf 1.68 _repository(repository)
|
87 mike 1.2 {
|
88 kumpf 1.11 PEG_METHOD_ENTER(TRC_HTTP,
89 "HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator");
90
|
91 a.arora 1.36 _authenticationManager.reset(new AuthenticationManager());
|
92 kumpf 1.11
93 PEG_METHOD_EXIT();
|
94 mike 1.2 }
95
96 HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator()
97 {
|
98 kumpf 1.11 PEG_METHOD_ENTER(TRC_HTTP,
99 "HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator");
100
101 PEG_METHOD_EXIT();
|
102 mike 1.2 }
103
|
104 kumpf 1.48 void HTTPAuthenticatorDelegator::enqueue(Message* message)
|
105 kumpf 1.24 {
106 handleEnqueue(message);
107 }
108
|
109 mike 1.2 void HTTPAuthenticatorDelegator::_sendResponse(
110 Uint32 queueId,
|
111 mike 1.54 Buffer& message,
|
112 j.alex 1.52 Boolean closeConnect)
|
113 mike 1.2 {
|
114 kumpf 1.11 PEG_METHOD_ENTER(TRC_HTTP,
115 "HTTPAuthenticatorDelegator::_sendResponse");
116
|
117 mike 1.2 MessageQueue* queue = MessageQueue::lookup(queueId);
118
119 if (queue)
120 {
121 HTTPMessage* httpMessage = new HTTPMessage(message);
|
122 kumpf 1.68 httpMessage->dest = queue->getQueueId();
123
|
124 j.alex 1.52 httpMessage->setCloseConnect(closeConnect);
|
125 kumpf 1.24
|
126 mike 1.2 queue->enqueue(httpMessage);
127 }
|
128 kumpf 1.11
129 PEG_METHOD_EXIT();
|
130 mike 1.2 }
131
|
132 gerarda 1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
133 void HTTPAuthenticatorDelegator::_sendSuccess(
134 Uint32 queueId,
|
135 j.alex 1.52 const String& authResponse,
136 Boolean closeConnect)
|
137 gerarda 1.22 {
138 PEG_METHOD_ENTER(TRC_HTTP,
139 "HTTPAuthenticatorDelegator::_sendSuccess");
140
141 //
142 // build OK (200) response message
143 //
144
|
145 mike 1.54 Buffer message;
|
146 gerarda 1.22 XmlWriter::appendOKResponseHeader(message, authResponse);
147
|
148 j.alex 1.52 _sendResponse(queueId, message,closeConnect);
|
149 gerarda 1.22
150 PEG_METHOD_EXIT();
151 }
152 #endif
153
|
154 mike 1.2 void HTTPAuthenticatorDelegator::_sendChallenge(
155 Uint32 queueId,
|
156 marek 1.100 const String& errorDetail,
|
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 marek 1.100 XmlWriter::appendUnauthorizedResponseHeader(
169 message,
170 errorDetail,
171 authResponse);
|
172 mike 1.2
|
173 j.alex 1.52 _sendResponse(queueId, message,closeConnect);
|
174 kumpf 1.11
175 PEG_METHOD_EXIT();
|
176 mike 1.2 }
177
178
|
179 kumpf 1.30 void HTTPAuthenticatorDelegator::_sendHttpError(
|
180 mike 1.2 Uint32 queueId,
|
181 kumpf 1.30 const String& status,
182 const String& cimError,
|
183 j.alex 1.52 const String& pegasusError,
184 Boolean closeConnect)
|
185 mike 1.2 {
|
186 kumpf 1.11 PEG_METHOD_ENTER(TRC_HTTP,
|
187 kumpf 1.30 "HTTPAuthenticatorDelegator::_sendHttpError");
|
188 kumpf 1.11
|
189 mike 1.2 //
|
190 kumpf 1.11 // build error response message
|
191 mike 1.2 //
192
|
193 mike 1.54 Buffer message;
|
194 kumpf 1.30 message = XmlWriter::formatHttpErrorRspMessage(
195 status,
196 cimError,
197 pegasusError);
|
198 mike 1.2
|
199 j.alex 1.52 _sendResponse(queueId, message,closeConnect);
|
200 kumpf 1.11
201 PEG_METHOD_EXIT();
|
202 mike 1.2 }
203
|
204 mday 1.5
205 void HTTPAuthenticatorDelegator::handleEnqueue(Message *message)
|
206 mike 1.2 {
|
207 kumpf 1.11 PEG_METHOD_ENTER(TRC_HTTP,
208 "HTTPAuthenticatorDelegator::handleEnqueue");
|
209 mike 1.2
|
210 kumpf 1.11 if (!message)
211 {
212 PEG_METHOD_EXIT();
|
213 mike 1.2 return;
|
214 kumpf 1.11 }
|
215 mike 1.2
|
216 kumpf 1.11 // Flag indicating whether the message should be deleted after handling.
217 // This should be set to false by handleHTTPMessage when the message is
218 // passed as is to another queue.
219 Boolean deleteMessage = true;
|
220 kumpf 1.68
|
221 kumpf 1.93 try
|
222 mike 1.2 {
|
223 dmitry.mikulin 1.80 if (message->getType() == HTTP_MESSAGE)
224 {
225 handleHTTPMessage((HTTPMessage*)message, deleteMessage);
226 }
227 }
228 catch (...)
229 {
230 if (deleteMessage)
231 {
|
232 marek 1.86 PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4,
|
233 dmitry.mikulin 1.80 "Exception caught, deleting Message in "
234 "HTTPAuthenticator::handleEnqueue");
|
235 kumpf 1.93
|
236 dmitry.mikulin 1.80 delete message;
237 }
238 throw;
|
239 mike 1.2 }
240
241 if (deleteMessage)
242 {
|
243 marek 1.86 PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4,
|
244 j.alex 1.52 "Deleting Message in HTTPAuthenticator::handleEnqueue");
245
|
246 mike 1.2 delete message;
247 }
|
248 kumpf 1.11
249 PEG_METHOD_EXIT();
|
250 mday 1.5 }
251
252 void HTTPAuthenticatorDelegator::handleEnqueue()
253 {
|
254 kumpf 1.11 PEG_METHOD_ENTER(TRC_HTTP,
255 "HTTPAuthenticatorDelegator::handleEnqueue");
256
|
257 mday 1.5 Message* message = dequeue();
|
258 kumpf 1.68 if (message)
|
259 kumpf 1.82 {
260 handleEnqueue(message);
261 }
|
262 kumpf 1.11
263 PEG_METHOD_EXIT();
|
264 mike 1.2 }
265
266 void HTTPAuthenticatorDelegator::handleHTTPMessage(
267 HTTPMessage* httpMessage,
|
268 kumpf 1.68 Boolean& deleteMessage)
269 {
|
270 kumpf 1.11 PEG_METHOD_ENTER(TRC_HTTP,
271 "HTTPAuthenticatorDelegator::handleHTTPMessage");
272
|
273 kumpf 1.72 PEGASUS_ASSERT(httpMessage->message.size() != 0);
274
|
275 mike 1.2 deleteMessage = true;
276
277 //
278 // Save queueId:
279 //
280 Uint32 queueId = httpMessage->queueId;
281
282 //
283 // Parse the HTTP message:
284 //
285 String startLine;
286 Array<HTTPHeader> headers;
287 Uint32 contentLength;
|
288 j.alex 1.52 Boolean closeConnect = false;
|
289 mike 1.2
|
290 thilo.boehm 1.77 //
291 // Process M-POST and POST messages:
292 //
293
|
294 marek 1.84 PEG_TRACE_CSTRING(
295 TRC_HTTP,
|
296 thilo.boehm 1.90 Tracer::LEVEL3,
|
297 marek 1.84 "HTTPAuthenticatorDelegator - HTTP processing start");
|
298 thilo.boehm 1.77
|
299 marek 1.98 // parse the received HTTPMessage
300 // parse function will return false if more than PEGASUS_MAXELEMENTS_NUM
301 // headers were detected in the message
302 if (!httpMessage->parse(startLine, headers, contentLength))
303 {
304 throw TooManyHTTPHeadersException();
305 }
|
306 kumpf 1.68
|
307 j.alex 1.52 //
308 // Check for Connection: Close
309 //
|
310 kumpf 1.94 const char* connectClose;
|
311 kumpf 1.68 if (HTTPMessage::lookupHeader(
|
312 kumpf 1.94 headers, _HTTP_HEADER_CONNECTION, connectClose, false))
|
313 j.alex 1.52 {
|
314 kumpf 1.94 if (System::strcasecmp(connectClose, "Close") == 0)
|
315 kumpf 1.68 {
|
316 marek 1.70 PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL3,
|
317 kumpf 1.68 "Header in HTTP Message Contains a Connection: Close");
|
318 j.alex 1.52 closeConnect = true;
319 httpMessage->setCloseConnect(closeConnect);
|
320 kumpf 1.68 }
|
321 j.alex 1.52 }
322
|
323 kumpf 1.35 //
|
324 thilo.boehm 1.77 // Check and set languages
325 //
326 AcceptLanguageList acceptLanguages;
327 ContentLanguageList contentLanguages;
328 try
329 {
330 // Get and validate the Accept-Language header, if set
331 String acceptLanguageHeader;
332 if (HTTPMessage::lookupHeader(
333 headers,
334 _HTTP_HEADER_ACCEPT_LANGUAGE,
335 acceptLanguageHeader,
336 false))
337 {
338 acceptLanguages = LanguageParser::parseAcceptLanguageHeader(
339 acceptLanguageHeader);
340 httpMessage->acceptLanguagesDecoded = true;
341 }
342
343 // Get and validate the Content-Language header, if set
344 String contentLanguageHeader;
345 thilo.boehm 1.77 if (HTTPMessage::lookupHeader(
346 headers,
347 _HTTP_HEADER_CONTENT_LANGUAGE,
348 contentLanguageHeader,
349 false))
350 {
351 contentLanguages = LanguageParser::parseContentLanguageHeader(
352 contentLanguageHeader);
353 httpMessage->contentLanguagesDecoded = true;
354 }
355 }
356 catch (Exception& e)
357 {
358 // clear any existing languages to force messages to come from the
359 // root bundle
360 Thread::clearLanguages();
361 MessageLoaderParms msgParms(
362 "Pegasus.Server.HTTPAuthenticatorDelegator.REQUEST_NOT_VALID",
363 "request-not-valid");
364 String msg(MessageLoader::getMessage(msgParms));
365
366 thilo.boehm 1.77 _sendHttpError(
367 queueId,
368 HTTP_STATUS_BADREQUEST,
369 msg,
370 e.getMessage(),
371 closeConnect);
372 PEG_METHOD_EXIT();
373 return;
374 }
375
|
376 kumpf 1.81 Thread::setLanguages(acceptLanguages);
|
377 thilo.boehm 1.77 httpMessage->acceptLanguages = acceptLanguages;
378 httpMessage->contentLanguages = contentLanguages;
379
380 //
381 // Parse the request line:
382 //
383 String methodName;
384 String requestUri;
385 String httpVersion;
386 HttpMethod httpMethod = HTTP_METHOD__POST;
387
388 HTTPMessage::parseRequestLine(
389 startLine, methodName, requestUri, httpVersion);
390
391 //
392 // Set HTTP method for the request
393 //
394 if (methodName == _HTTP_METHOD_MPOST)
395 {
396 httpMethod = HTTP_METHOD_M_POST;
397 }
398 thilo.boehm 1.77
399 if (methodName != _HTTP_METHOD_MPOST && methodName != _HTTP_METHOD)
400 {
401 // Only POST and M-POST are implemented by this server
402 _sendHttpError(
403 queueId,
404 HTTP_STATUS_NOTIMPLEMENTED,
405 String::EMPTY,
406 String::EMPTY,
407 closeConnect);
408 PEG_METHOD_EXIT();
409 return;
410 }
411
412 if ((httpMethod == HTTP_METHOD_M_POST) &&
413 (httpVersion == _HTTP_VERSION_1_0))
414 {
415 //
416 // M-POST method is not valid with version 1.0
417 //
418 _sendHttpError(
419 thilo.boehm 1.77 queueId,
420 HTTP_STATUS_BADREQUEST,
421 String::EMPTY,
422 String::EMPTY,
423 closeConnect);
424 PEG_METHOD_EXIT();
425 return;
426 }
427
|
428 marek 1.84 PEG_TRACE_CSTRING(
429 TRC_AUTHENTICATION,
|
430 marek 1.86 Tracer::LEVEL3,
|
431 marek 1.84 "HTTPAuthenticatorDelegator - Authentication processing start");
|
432 thilo.boehm 1.77
433 //
|
434 h.sterling 1.34 // Handle authentication:
435 //
436 ConfigManager* configManager = ConfigManager::getInstance();
|
437 kumpf 1.93 Boolean enableAuthentication =
|
438 thilo.boehm 1.77 ConfigManager::parseBooleanValue(configManager->getCurrentValue(
439 _CONFIG_PARAM_ENABLEAUTHENTICATION));
|
440 sushma.fernandes 1.71
|
441 marek 1.100 AuthenticationStatus authStatus(AUTHSC_UNAUTHORIZED);
442 if (httpMessage->authInfo->isConnectionAuthenticated())
443 {
444 authStatus = AuthenticationStatus(AUTHSC_SUCCESS);
445 }
446
|
447 h.sterling 1.34
|
448 kumpf 1.68 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
449 CIMKerberosSecurityAssociation* sa = NULL;
450 // The presence of a Security Association indicates that Kerberos is
451 // being used.
452 // Reset flag for subsequent calls to indicate that no Authorization
453 // record was sent. If one was sent the flag will be appropriately reset
454 // later.
455 // The sa is maintained while the connection is active.
456 sa = httpMessage->authInfo->getSecurityAssociation();
457 if (sa)
458 {
459 sa->setClientSentAuthorization(false);
460 }
461 #endif
|
462 david 1.57
|
463 thilo.boehm 1.77 if (enableAuthentication)
|
464 h.sterling 1.34 {
|
465 thilo.boehm 1.77
|
466 kumpf 1.68 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
467 // If we are using Kerberos (sa pointer is set), the client has
468 // already authenticated, and the client is NOT attempting to
469 // re-authenticate (dermined by an Authorization record being sent),
470 // then we want to set the local authenticate flag to true so that
471 // the authentication logic is skipped.
|
472 kumpf 1.94 const char* authstr;
|
473 david 1.57 if (sa && sa->getClientAuthenticated() &&
|
474 kumpf 1.68 !HTTPMessage::lookupHeader(
475 headers, "Authorization", authstr, false))
476 {
|
477 marek 1.100 authStatus = AuthenticationStatus(AUTHSC_SUCCESS);
|
478 kumpf 1.68 }
|
479 david 1.57 #endif
|
480 marek 1.100 if (authStatus.isSuccess())
|
481 thilo.boehm 1.77 {
|
482 kumpf 1.93 if (httpMessage->authInfo->getAuthType()==
|
483 thilo.boehm 1.77 AuthenticationInfoRep::AUTH_TYPE_SSL)
484 {
|
485 kumpf 1.82 // Get the user name associated with the certificate (using the
486 // certificate chain, if necessary).
|
487 kumpf 1.63
|
488 kumpf 1.82 String certUserName;
489 String issuerName;
490 String subjectName;
491 char serialNumber[32];
|
492 sushma.fernandes 1.76
|
493 kumpf 1.82 PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL3,
494 "Client was authenticated via trusted SSL certificate.");
|
495 kumpf 1.68
|
496 kumpf 1.82 String trustStore =
497 configManager->getCurrentValue("sslTrustStore");
|
498 h.sterling 1.59
|
499 kumpf 1.82 if (FileSystem::isDirectory(
500 ConfigManager::getHomedPath(trustStore)))
|
501 h.sterling 1.59 {
|
502 kumpf 1.82 PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4,
503 "Truststore is a directory, lookup username");
|
504 kumpf 1.68
|
505 kumpf 1.82 // Get the client certificate chain to determine the
506 // correct username mapping. Starting with the peer
507 // certificate, work your way up the chain towards the
508 // root certificate until a match is found in the
509 // repository.
510 Array<SSLCertificateInfo*> clientCertificateChain =
511 httpMessage->authInfo->getClientCertificateChain();
512 SSLCertificateInfo* clientCertificate = NULL;
|
513 kumpf 1.68
|
514 kumpf 1.82 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
515 "Client certificate chain length: %d.",
516 clientCertificateChain.size()));
|
517 kumpf 1.68
|
518 kumpf 1.82 Uint32 loopCount = clientCertificateChain.size() - 1;
519 for (Uint32 i = 0; i <= loopCount ; i++)
|
520 kumpf 1.63 {
|
521 kumpf 1.82 clientCertificate = clientCertificateChain[i];
522 if (clientCertificate == NULL)
523 {
524 MessageLoaderParms msgParms(
525 "Pegasus.Server.HTTPAuthenticatorDelegator."
526 "BAD_CERTIFICATE",
527 "The certificate used for authentication is "
528 "not valid.");
529 _sendHttpError(
530 queueId,
531 HTTP_STATUS_UNAUTHORIZED,
532 String::EMPTY,
533 MessageLoader::getMessage(msgParms),
534 closeConnect);
535 PEG_METHOD_EXIT();
536 return;
537 }
|
538 thilo.boehm 1.89 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
539 "Certificate toString %s",
540 (const char*)
541 clientCertificate->toString().getCString()));
|
542 kumpf 1.82
543 // Get certificate properties
544 issuerName = clientCertificate->getIssuerName();
545 sprintf(serialNumber, "%lu",
|
546 kumpf 1.87 (unsigned long)
547 clientCertificate->getSerialNumber());
|
548 kumpf 1.82 subjectName = clientCertificate->getSubjectName();
549
550 //
551 // The truststore type key property is deprecated. To
552 // retain backward compatibility, add the truststore
553 // type property to the key bindings and set it to
554 // cimserver truststore.
555 //
556
557 // Construct the corresponding PG_SSLCertificate
558 // instance
559 Array<CIMKeyBinding> keyBindings;
560 keyBindings.append(CIMKeyBinding(
561 "IssuerName", issuerName, CIMKeyBinding::STRING));
562 keyBindings.append(CIMKeyBinding(
563 "SerialNumber",
564 serialNumber,
565 CIMKeyBinding::STRING));
566 keyBindings.append(CIMKeyBinding("TruststoreType",
567 PG_SSLCERTIFICATE_TSTYPE_VALUE_SERVER));
568
569 kumpf 1.82 CIMObjectPath cimObjectPath(
570 "localhost",
571 PEGASUS_NAMESPACENAME_CERTIFICATE,
572 PEGASUS_CLASSNAME_CERTIFICATE,
573 keyBindings);
574
|
575 thilo.boehm 1.89 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
576 "Client Certificate COP: %s",
577 (const char*)
578 cimObjectPath.toString().getCString()));
|
579 kumpf 1.82
580 CIMInstance cimInstance;
581 CIMValue value;
582 Uint32 pos;
583 String userName;
584
585 // Attempt to get the username registered to the
586 // certificate
587 try
|
588 h.sterling 1.59 {
|
589 kumpf 1.82 cimInstance = _repository->getInstance(
590 PEGASUS_NAMESPACENAME_CERTIFICATE,
591 cimObjectPath);
592
593 pos =
594 cimInstance.findProperty("RegisteredUserName");
595
596 if (pos != PEG_NOT_FOUND &&
597 !(value = cimInstance.getProperty(pos).
598 getValue()).isNull())
599 {
600 value.get(userName);
|
601 h.sterling 1.59
|
602 kumpf 1.82 //
603 // If a user name is specified, our search is
604 // complete
605 //
606 if (userName.size())
607 {
|
608 thilo.boehm 1.89 PEG_TRACE((TRC_HTTP, Tracer::LEVEL3,
609 "User name for certificate is %s",
610 (const char*)userName.getCString()));
|
611 kumpf 1.82 certUserName = userName;
612 break;
613 }
614
615 // No user name is specified; continue up the
616 // chain
617 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
618 "The certificate at level %u has no "
619 "associated username; moving up the "
620 "chain",
621 i));
622 }
623 else
|
624 kumpf 1.63 {
|
625 marek 1.84 PEG_TRACE_CSTRING(
626 TRC_HTTP,
627 Tracer::LEVEL3,
|
628 kumpf 1.82 "HTTPAuthenticatorDelegator - Bailing, no "
629 "username is registered to this "
630 "certificate.");
|
631 kumpf 1.63 }
|
632 kumpf 1.68 }
|
633 kumpf 1.82 catch (CIMException& e)
|
634 h.sterling 1.59 {
|
635 kumpf 1.82 // this certificate did not have a registration
636 // associated with it; continue up the chain
637 if (e.getCode() == CIM_ERR_NOT_FOUND)
638 {
639 PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4,
640 "No registration for this certificate; "
641 "try next certificate in chain");
642 continue;
643 }
644 else
645 {
|
646 harsha.bm 1.97 PEG_TRACE((TRC_HTTP,Tracer::LEVEL1,
647 "HTTPAuthenticatorDelegator- Bailing,the "
648 "certificate used for authentication "
649 "is not valid for client IP address "
650 "%s.",
651 (const char*)
652 httpMessage->ipAddress.getCString())
653 );
|
654 marek 1.84
|
655 kumpf 1.82 MessageLoaderParms msgParms(
656 "Pegasus.Server.HTTPAuthenticatorDelegator."
657 "BAD_CERTIFICATE",
658 "The certificate used for authentication "
659 "is not valid.");
660 String msg(MessageLoader::getMessage(msgParms));
661 _sendHttpError(
662 queueId,
663 HTTP_STATUS_UNAUTHORIZED,
664 String::EMPTY,
665 msg,
666 closeConnect);
667 PEG_METHOD_EXIT();
668 return;
669 }
|
670 kumpf 1.68 }
|
671 kumpf 1.82 catch (...)
|
672 h.sterling 1.59 {
|
673 kumpf 1.82 // This scenario can occur if a certificate cached
674 // on the server was deleted openssl would not pick
675 // up the deletion but we would pick it up here
676 // when we went to look it up in the repository
|
677 marek 1.84
|
678 harsha.bm 1.97 PEG_TRACE((TRC_HTTP,Tracer::LEVEL1,
679 "HTTPAuthenticatorDelegator- Bailing,the "
|
680 kumpf 1.82 "certificate used for authentication is "
|
681 harsha.bm 1.97 "not valid for client IP address %s.",
682 (const char*)
683 httpMessage->ipAddress.getCString()));
684
|
685 kumpf 1.68 MessageLoaderParms msgParms(
686 "Pegasus.Server.HTTPAuthenticatorDelegator."
687 "BAD_CERTIFICATE",
688 "The certificate used for authentication is "
689 "not valid.");
|
690 kumpf 1.63 String msg(MessageLoader::getMessage(msgParms));
|
691 kumpf 1.68 _sendHttpError(
692 queueId,
693 HTTP_STATUS_UNAUTHORIZED,
694 String::EMPTY,
695 msg,
696 closeConnect);
|
697 kumpf 1.63 PEG_METHOD_EXIT();
698 return;
|
699 h.sterling 1.59 }
|
700 kumpf 1.82 } //end for clientcertificatechain
701 } //end sslTrustStore directory
702 else
703 {
704 // trustStore is a single CA file, lookup username
705 // user was already verified as a valid system user during
706 // server startup
707 certUserName =
708 configManager->getCurrentValue("sslTrustStoreUserName");
709 }
710
711 //
712 // Validate user information
713 //
|
714 kumpf 1.63
|
715 kumpf 1.82 if (certUserName == String::EMPTY)
716 {
|
717 harsha.bm 1.97 PEG_TRACE((TRC_HTTP,Tracer::LEVEL1,
718 "HTTPAuthenticatorDelegator-No username is registered "
719 "to this certificate for client IP address %s.",
720 (const char*)httpMessage->ipAddress.getCString()));
721
|
722 kumpf 1.82 MessageLoaderParms msgParms(
723 "Pegasus.Server.HTTPAuthenticatorDelegator."
724 "BAD_CERTIFICATE_USERNAME",
725 "No username is registered to this certificate.");
726 _sendHttpError(
727 queueId,
728 HTTP_STATUS_UNAUTHORIZED,
729 String::EMPTY,
730 MessageLoader::getMessage(msgParms),
731 closeConnect);
732 PEG_METHOD_EXIT();
733 return;
734 }
|
735 kumpf 1.63
|
736 marek 1.100 authStatus =
737 _authenticationManager->validateUserForHttpAuth(
|
738 marek 1.99 certUserName,
|
739 marek 1.100 httpMessage->authInfo);
740
741 if (!authStatus.isSuccess())
|
742 kumpf 1.82 {
743 PEG_AUDIT_LOG(logCertificateBasedUserValidation(
744 certUserName,
745 issuerName,
746 subjectName,
747 serialNumber,
748 httpMessage->ipAddress,
749 false));
750 MessageLoaderParms msgParms(
751 "Pegasus.Server.HTTPAuthenticatorDelegator."
752 "CERTIFICATE_USER_NOT_VALID",
753 "User '$0' registered to this certificate is not a "
754 "valid user.",
755 certUserName);
|
756 marek 1.100
|
757 kumpf 1.82 _sendHttpError(
758 queueId,
759 HTTP_STATUS_UNAUTHORIZED,
760 String::EMPTY,
761 MessageLoader::getMessage(msgParms),
762 closeConnect);
763 PEG_METHOD_EXIT();
764 return;
765 }
|
766 sushma.fernandes 1.69
|
767 sushma.fernandes 1.76 PEG_AUDIT_LOG(logCertificateBasedUserValidation(
768 certUserName,
769 issuerName,
770 subjectName,
771 serialNumber,
772 httpMessage->ipAddress,
|
773 kumpf 1.82 true));
774
775 httpMessage->authInfo->setAuthenticatedUser(certUserName);
|
776 h.sterling 1.44
|
777 marek 1.84 PEG_TRACE((
|
778 kumpf 1.82 TRC_HTTP,
|
779 marek 1.86 Tracer::LEVEL4,
|
780 kumpf 1.82 "HTTPAuthenticatorDelegator - The trusted client "
|
781 marek 1.84 "certificate is registered to %s.",
782 (const char*) certUserName.getCString()));
|
783 thilo.boehm 1.77 } // end AuthenticationInfoRep::AUTH_TYPE_SSL
784
785 #ifdef PEGASUS_OS_ZOS
|
786 kumpf 1.93 if (httpMessage->authInfo->getAuthType()==
|
787 thilo.boehm 1.77 AuthenticationInfoRep::AUTH_TYPE_ZOS_ATTLS)
788 {
|
789 kumpf 1.93 String connectionUserName =
|
790 thilo.boehm 1.77 httpMessage->authInfo->getConnectionUser();
791
|
792 kumpf 1.93 // If authenticated user not the connected user
|
793 thilo.boehm 1.77 // then check CIMSERV profile.
794 if (!String::equalNoCase(connectionUserName,
795 httpMessage->authInfo->getAuthenticatedUser()))
796 {
|
797 h.sterling 1.43
|
798 thilo.boehm 1.77 #ifdef PEGASUS_ZOS_SECURITY
|
799 kumpf 1.93 if ( !CheckProfileCIMSERVclassWBEM(connectionUserName,
|
800 thilo.boehm 1.77 __READ_RESOURCE))
801 {
|
802 kumpf 1.93 Logger::put_l(Logger::STANDARD_LOG, ZOS_SECURITY_NAME,
|
803 thilo.boehm 1.77 Logger::WARNING,
|
804 kumpf 1.88 MessageLoaderParms(
805 "Pegasus.Server.HTTPAuthenticatorDelegator."
806 "ATTLS_NOREAD_CIMSERV_ACCESS.PEGASUS_OS_ZOS",
807 "Request UserID $0 doesn't have READ permission"
808 " to profile CIMSERV CL(WBEM).",
809 connectionUserName));
|
810 thilo.boehm 1.77
|
811 thilo.boehm 1.78 PEG_AUDIT_LOG(logCertificateBasedUserValidation(
|
812 kumpf 1.82 connectionUserName,
813 String::EMPTY,
814 String::EMPTY,
815 String::EMPTY,
816 httpMessage->ipAddress,
817 false));
|
818 thilo.boehm 1.78
|
819 thilo.boehm 1.77 _sendHttpError(
820 queueId,
821 HTTP_STATUS_UNAUTHORIZED,
822 String::EMPTY,
823 String::EMPTY,
824 closeConnect);
825
826 PEG_METHOD_EXIT();
827 return;
828 }
829 #endif
830 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
|
831 kumpf 1.82 "Client UserID '%s' was authenticated via AT-TLS.",
|
832 thilo.boehm 1.77 (const char*)connectionUserName.getCString()));
833
834 httpMessage->authInfo->setAuthenticatedUser(
835 connectionUserName);
836
|
837 kumpf 1.93 // For audit loging, only the mapping of the client IP to
|
838 thilo.boehm 1.77 // the resolved user ID is from interest.
|
839 kumpf 1.93 // The SAF facility logs the certificate validation and
|
840 thilo.boehm 1.77 // the mapping of certificate subject to a local userID.
841 PEG_AUDIT_LOG(logCertificateBasedUserValidation(
842 connectionUserName,
843 String::EMPTY,
844 String::EMPTY,
845 String::EMPTY,
846 httpMessage->ipAddress,
847 true));
|
848 h.sterling 1.43
|
849 thilo.boehm 1.77 }// end is authenticated ?
|
850 h.sterling 1.34
|
851 thilo.boehm 1.77 } // end AuthenticationInfoRep::AUTH_TYPE_ZOS_ATTLS
|
852 humberto 1.33
|
853 kumpf 1.93 if (httpMessage->authInfo->getAuthType()==
|
854 thilo.boehm 1.77 AuthenticationInfoRep::AUTH_TYPE_ZOS_LOCAL_DOMIAN_SOCKET)
855 {
|
856 kumpf 1.93 String connectionUserName =
|
857 thilo.boehm 1.77 httpMessage->authInfo->getConnectionUser();
|
858 kumpf 1.68
|
859 kumpf 1.93 String requestUserName;
|
860 thilo.boehm 1.77 String authHeader;
861 String authHttpType;
862 String cookie;
863
|
864 kumpf 1.93 // if lookupHeader() is not successfull parseLocalAuthHeader()
|
865 thilo.boehm 1.77 // must not be called !!
866 if ( HTTPMessage::lookupHeader(headers,
867 _HTTP_HEADER_PEGASUSAUTHORIZATION, authHeader, false)&&
868 HTTPMessage::parseLocalAuthHeader(authHeader,
869 authHttpType, requestUserName, cookie))
870 {
871 String cimServerUserName = System::getEffectiveUserName();
|
872 humberto 1.33
|
873 thilo.boehm 1.77 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
874 "CIM server UserID = '%s', "
875 "Request UserID = '%s', "
876 "Local authenticated UserID = '%s'.",
877 (const char*) cimServerUserName.getCString(),
878 (const char*) requestUserName.getCString(),
879 (const char*) connectionUserName.getCString()
880 ));
881
|
882 kumpf 1.93 // if the request name and the user connected to the socket
883 // are the same, or if the currnet user running the
|
884 thilo.boehm 1.77 // cim server and the connected user are the same then
885 // assign the request user id as authenticated user id.
886 if( String::equalNoCase(
|
887 kumpf 1.93 requestUserName,connectionUserName) ||
|
888 thilo.boehm 1.77 String::equalNoCase(
889 cimServerUserName,connectionUserName))
890 {
891 // If the designate new authenticated user, the user of
|
892 kumpf 1.93 // the request, is not already the authenticated user
|
893 thilo.boehm 1.77 // then set the authenticated user and check CIMSERV.
894 if (!String::equalNoCase(requestUserName,
895 httpMessage->authInfo->getAuthenticatedUser()))
896 {
|
897 mike 1.2
|
898 thilo.boehm 1.77 #ifdef PEGASUS_ZOS_SECURITY
|
899 kumpf 1.93 if ( !CheckProfileCIMSERVclassWBEM(requestUserName,
|
900 thilo.boehm 1.77 __READ_RESOURCE))
901 {
|
902 kumpf 1.93 Logger::put_l(Logger::STANDARD_LOG,
903 ZOS_SECURITY_NAME,
|
904 thilo.boehm 1.77 Logger::WARNING,
|
905 kumpf 1.88 MessageLoaderParms(
|
906 thilo.boehm 1.77 "Pegasus.Server.HTTPAuthenticatorDelegator."
907 "UNIXSOCKET_NOREAD_CIMSERV_ACCESS."
908 "PEGASUS_OS_ZOS",
909 "Request UserID $0 doesn't have READ "
910 "permission to profile "
911 "CIMSERV CL(WBEM).",
|
912 kumpf 1.88 requestUserName));
|
913 thilo.boehm 1.77
914 _sendHttpError(
915 queueId,
916 HTTP_STATUS_UNAUTHORIZED,
917 String::EMPTY,
918 String::EMPTY,
919 closeConnect);
920
921 PEG_METHOD_EXIT();
|
922 kumpf 1.82 return;
|
923 thilo.boehm 1.77 }
924 #endif
|
925 kumpf 1.93 // It is not necessary to check remote privileged
926 // user access for local connections;
|
927 thilo.boehm 1.79 // set the flag to "check done"
928 httpMessage->authInfo->
929 setRemotePrivilegedUserAccessChecked();
930
|
931 thilo.boehm 1.77 httpMessage->authInfo->setAuthenticatedUser(
932 requestUserName);
|
933 mike 1.2
|
934 thilo.boehm 1.77 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
935 "New authenticated User = '%s'.",
936 (const char*)requestUserName.getCString()
937 ));
938
939 } // end changed authenticated user
940
941 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
942 "User authenticated for request = '%s'.",
943 (const char*)httpMessage->authInfo->
944 getAuthenticatedUser().getCString()
945 ));
|
946 thilo.boehm 1.78
947 // Write local authentication audit record.
948 PEG_AUDIT_LOG(logLocalAuthentication(
949 requestUserName,true));
950
951 } // end select authenticated user
952 else
953 {
954 PEG_AUDIT_LOG(logLocalAuthentication(
955 requestUserName,false));
956
957 PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
958 "User '%s' not authorized for request",
959 (const char*)requestUserName.getCString()));
960
961 _sendHttpError(
962 queueId,
963 HTTP_STATUS_UNAUTHORIZED,
964 String::EMPTY,
965 String::EMPTY,
966 closeConnect);
967 thilo.boehm 1.78
968 PEG_METHOD_EXIT();
969 return;
970 }
|
971 thilo.boehm 1.77 } // end lookup header
972 else
|
973 kumpf 1.93 {
|
974 thilo.boehm 1.77 MessageLoaderParms msgParms(
975 "Pegasus.Server.HTTPAuthenticatorDelegator."
976 "AUTHORIZATION_HEADER_ERROR",
977 "Authorization header error");
978 String msg(MessageLoader::getMessage(msgParms));
979 _sendHttpError(
980 queueId,
981 HTTP_STATUS_BADREQUEST,
982 String::EMPTY,
983 msg,
984 closeConnect);
|
985 kumpf 1.19
|
986 thilo.boehm 1.77 PEG_METHOD_EXIT();
987 return;
988 }
989 } // end AuthenticationInfoRep::AUTH_TYPE_ZOS_LOCAL_DOMIAN_SOCKET
990 #endif
991 } // end isRequestAuthenticated
|
992 kumpf 1.82 else
|
993 thilo.boehm 1.77 { // !isRequestAuthenticated
|
994 mike 1.56
|
995 thilo.boehm 1.77 String authorization;
|
996 mike 1.2
|
997 kumpf 1.68 //
|
998 thilo.boehm 1.77 // do Local/Pegasus authenticatio
|
999 kumpf 1.68 //
1000 if (HTTPMessage::lookupHeader(headers,
|
1001 thilo.boehm 1.77 _HTTP_HEADER_PEGASUSAUTHORIZATION, authorization, false))
|
1002 kumpf 1.28 {
|
1003 kumpf 1.68 try
1004 {
1005 //
1006 // Do pegasus/local authentication
1007 //
|
1008 marek 1.100 authStatus =
|
1009 kumpf 1.68 _authenticationManager->performPegasusAuthentication(
1010 authorization,
1011 httpMessage->authInfo);
|
1012 mike 1.2
|
1013 marek 1.100 if (!authStatus.isSuccess())
|
1014 kumpf 1.68 {
1015 String authResp;
|
1016 mike 1.2
|
1017 kumpf 1.68 authResp = _authenticationManager->
1018 getPegasusAuthResponseHeader(
1019 authorization,
1020 httpMessage->authInfo);
|
1021 kumpf 1.28
|
1022 marek 1.100 if (authResp.size() > 0)
|
1023 kumpf 1.68 {
|
1024 marek 1.100 if (authStatus.doChallenge())
1025 {
1026 _sendChallenge(
1027 queueId,
1028 authStatus.getErrorDetail(),
1029 authResp,
1030 closeConnect);
1031 }
1032 else
1033 {
1034 _sendHttpError(
1035 queueId,
1036 authStatus.getHttpStatus(),
1037 String::EMPTY,
1038 authStatus.getErrorDetail(),
1039 closeConnect);
1040 }
|
1041 kumpf 1.68 }
1042 else
1043 {
1044 MessageLoaderParms msgParms(
1045 "Pegasus.Server.HTTPAuthenticatorDelegator."
1046 "AUTHORIZATION_HEADER_ERROR",
1047 "Authorization header error");
1048 String msg(MessageLoader::getMessage(msgParms));
1049 _sendHttpError(
1050 queueId,
1051 HTTP_STATUS_BADREQUEST,
1052 String::EMPTY,
1053 msg,
1054 closeConnect);
1055 }
1056
1057 PEG_METHOD_EXIT();
1058 return;
|
1059 kumpf 1.28 }
|
1060 kumpf 1.68 }
1061 catch (const CannotOpenFile&)
1062 {
1063 _sendHttpError(
1064 queueId,
1065 HTTP_STATUS_INTERNALSERVERERROR,
1066 String::EMPTY,
1067 String::EMPTY,
1068 closeConnect);
|
1069 kumpf 1.28 PEG_METHOD_EXIT();
1070 return;
|
1071 mike 1.2 }
|
1072 thilo.boehm 1.77 } // end PEGASUS/LOCAL authentication
|
1073 mike 1.2
|
1074 thilo.boehm 1.77 //
1075 // do HTTP authentication
1076 //
|
1077 kumpf 1.68 if (HTTPMessage::lookupHeader(
|
1078 kumpf 1.93 headers, _HTTP_HEADER_AUTHORIZATION,
1079 authorization, false))
|
1080 mike 1.2 {
|
1081 marek 1.101 authStatus =
|
1082 kumpf 1.82 _authenticationManager->performHttpAuthentication(
1083 authorization,
1084 httpMessage->authInfo);
|
1085 kumpf 1.68
|
1086 marek 1.101 #ifdef PEGASUS_PAM_SESSION_SECURITY
1087 if (authStatus.isPasswordExpired())
1088 {
1089 // if this is CIM-XML and Password Expired treat as success
1090 // expired password state is already stored in
1091 // AuthenticationInfo
1092 const char* cimOperation;
1093
1094 if (HTTPMessage::lookupHeader(
1095 headers,
1096 _HTTP_HEADER_CIMOPERATION,
1097 cimOperation,
1098 true))
1099 {
1100 authStatus = AuthenticationStatus(true);
1101 }
1102 }
1103 #endif
|
1104 marek 1.100 if (!authStatus.isSuccess())
|
1105 kumpf 1.82 {
1106 //ATTN: the number of challenges get sent for a
1107 // request on a connection can be pre-set.
|
1108 gerarda 1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
|
1109 kumpf 1.82 // Kerberos authentication needs access to the
1110 // AuthenticationInfo object for this session in
1111 // order to set up the reference to the
1112 // CIMKerberosSecurityAssociation object for this
1113 // session.
|
1114 kumpf 1.68
|
1115 kumpf 1.82 String authResp =
1116 _authenticationManager->getHttpAuthResponseHeader(
1117 httpMessage->authInfo);
|
1118 gerarda 1.22 #else
|
1119 kumpf 1.82 String authResp =
1120 _authenticationManager->getHttpAuthResponseHeader();
|
1121 gerarda 1.22 #endif
|
1122 marek 1.100 if (authResp.size() > 0)
|
1123 kumpf 1.82 {
|
1124 marek 1.100 if (authStatus.doChallenge())
1125 {
1126 _sendChallenge(
1127 queueId,
1128 authStatus.getErrorDetail(),
1129 authResp,
1130 closeConnect);
1131 }
1132 else
1133 {
1134 _sendHttpError(
1135 queueId,
1136 authStatus.getHttpStatus(),
1137 String::EMPTY,
1138 authStatus.getErrorDetail(),
1139 closeConnect);
1140 }
|
1141 kumpf 1.82 }
1142 else
1143 {
1144 MessageLoaderParms msgParms(
1145 "Pegasus.Server.HTTPAuthenticatorDelegator."
1146 "AUTHORIZATION_HEADER_ERROR",
1147 "Authorization header error");
1148 String msg(MessageLoader::getMessage(msgParms));
1149 _sendHttpError(
1150 queueId,
1151 HTTP_STATUS_BADREQUEST,
1152 String::EMPTY,
1153 msg,
1154 closeConnect);
1155 }
|
1156 kumpf 1.68
|
1157 kumpf 1.82 PEG_METHOD_EXIT();
1158 return;
1159 }
|
1160 kumpf 1.93 } // End if HTTP Authorization
|
1161 thilo.boehm 1.77
1162 } //end if (!isRequestAuthenticated)
1163
1164 } //end enableAuthentication
1165
|
1166 marek 1.84 PEG_TRACE_CSTRING(
1167 TRC_AUTHENTICATION,
|
1168 marek 1.86 Tracer::LEVEL3,
|
1169 marek 1.84 "HTTPAuthenticatorDelegator - Authentication processing ended");
|
1170 thilo.boehm 1.77
|
1171 kumpf 1.68
1172 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
|
1173 thilo.boehm 1.77 // The pointer to the sa is created in the authenticator so we need
1174 // to also assign it here.
1175 sa = httpMessage->authInfo->getSecurityAssociation();
1176 if (sa)
1177 {
1178 // 0 - continue, 1 = send success, 2 = send response
1179 Uint32 sendAction = 0;
1180
1181 // The following is processing to unwrap (decrypt) the request
1182 // from the client when using kerberos authentication.
1183 sa->unwrapRequestMessage(
|
1184 kumpf 1.93 httpMessage->message,
1185 contentLength,
1186 isRequestAuthenticated,
|
1187 thilo.boehm 1.77 sendAction);
|
1188 kumpf 1.68
|
1189 thilo.boehm 1.77 if (sendAction) // send success or send response
1190 {
1191 if (httpMessage->message.size() == 0)
|
1192 kumpf 1.68 {
|
1193 thilo.boehm 1.77 MessageLoaderParms msgParms(
1194 "Pegasus.Server.HTTPAuthenticatorDelegator."
1195 "AUTHORIZATION_HEADER_ERROR",
1196 "Authorization header error");
1197 String msg(MessageLoader::getMessage(msgParms));
1198 _sendHttpError(
1199 queueId,
1200 HTTP_STATUS_BADREQUEST,
1201 String::EMPTY,
1202 msg,
1203 closeConnect);
1204 }
1205 else
1206 {
1207 if (sendAction == 1) // Send success
|
1208 kumpf 1.68 {
|
1209 thilo.boehm 1.77 _sendSuccess(
|
1210 kumpf 1.68 queueId,
|
1211 thilo.boehm 1.77 String(
1212 httpMessage->message.getData(),
1213 httpMessage->message.size()),
|
1214 kumpf 1.68 closeConnect);
1215 }
|
1216 thilo.boehm 1.77
1217 if (sendAction == 2) // Send response
|
1218 kumpf 1.68 {
|
1219 thilo.boehm 1.77 _sendResponse(
1220 queueId,
1221 httpMessage->message,
1222 closeConnect);
1223 }
1224 }
|
1225 mike 1.2
|
1226 thilo.boehm 1.77 PEG_METHOD_EXIT();
1227 return;
1228 }
1229 }
1230 #endif
|
1231 gerarda 1.26
|
1232 marek 1.100 if (authStatus.isSuccess() || !enableAuthentication)
|
1233 thilo.boehm 1.77 {
1234 // Final bastion to ensure the remote privileged user access
1235 // check is done as it should be
1236 // check for remote privileged User Access
1237 if (!httpMessage->authInfo->getRemotePrivilegedUserAccessChecked())
1238 {
1239 // the AuthenticationHandler did not process the
1240 // enableRemotePrivilegedUserAccess check
1241 // time to do it ourselves
1242 String userName = httpMessage->authInfo->getAuthenticatedUser();
1243 if (!AuthenticationManager::isRemotePrivilegedUserAccessAllowed(
1244 userName))
1245 {
1246 // Send client a message that we can't proceed to talk
1247 // to him
1248 // HTTP 401 ?
1249 MessageLoaderParms msgParms(
1250 "Server.CIMOperationRequestAuthorizer."
1251 "REMOTE_NOT_ENABLED",
1252 "Remote privileged user access is not enabled.");
1253 String msg(MessageLoader::getMessage(msgParms));
1254 thilo.boehm 1.77 _sendHttpError(
1255 queueId,
1256 HTTP_STATUS_UNAUTHORIZED,
1257 String::EMPTY,
1258 msg,
1259 closeConnect);
|
1260 kumpf 1.68 PEG_METHOD_EXIT();
1261 return;
1262 }
|
1263 thilo.boehm 1.77 httpMessage->authInfo->setRemotePrivilegedUserAccessChecked();
|
1264 kumpf 1.68 }
|
1265 h.sterling 1.34
|
1266 thilo.boehm 1.77 //
|
1267 kumpf 1.83 // Determine the type of this request:
|
1268 thilo.boehm 1.77 //
|
1269 kumpf 1.83 // - A "CIMOperation" header indicates a CIM operation request
1270 // - A "CIMExport" header indicates a CIM export request
1271 // - A "/wsman" path in the start message indicates a WS-Man request
1272 //
1273
|
1274 kumpf 1.94 const char* cimOperation;
|
1275 thilo.boehm 1.77
1276 if (HTTPMessage::lookupHeader(
|
1277 kumpf 1.94 headers, _HTTP_HEADER_CIMOPERATION, cimOperation, true))
|
1278 mike 1.2 {
|
1279 marek 1.84 PEG_TRACE((
1280 TRC_HTTP,
1281 Tracer::LEVEL3,
|
1282 kumpf 1.94 "HTTPAuthenticatorDelegator - CIMOperation: %s",
1283 cimOperation));
|
1284 thilo.boehm 1.77
1285 MessageQueue* queue =
|
1286 kumpf 1.83 MessageQueue::lookup(_cimOperationMessageQueueId);
|
1287 thilo.boehm 1.77
1288 if (queue)
1289 {
1290 httpMessage->dest = queue->getQueueId();
1291
1292 try
1293 {
1294 queue->enqueue(httpMessage);
1295 }
1296 catch (const bad_alloc&)
|
1297 marek 1.67 {
|
1298 thilo.boehm 1.77 delete httpMessage;
|
1299 venkat.puvvada 1.96 HTTPConnection *httpQueue =
1300 dynamic_cast<HTTPConnection*>(
1301 MessageQueue::lookup(queueId));
1302 if (httpQueue)
1303 {
1304 httpQueue->handleInternalServerError(0, true);
1305 }
|
1306 marek 1.67 PEG_METHOD_EXIT();
|
1307 thilo.boehm 1.77 deleteMessage = false;
|
1308 marek 1.67 return;
1309 }
|
1310 thilo.boehm 1.77 deleteMessage = false;
|
1311 marek 1.67 }
|
1312 thilo.boehm 1.77 }
1313 else if (HTTPMessage::lookupHeader(
|
1314 kumpf 1.94 headers, _HTTP_HEADER_CIMEXPORT, cimOperation, true))
|
1315 thilo.boehm 1.77 {
|
1316 marek 1.84 PEG_TRACE((
1317 TRC_AUTHENTICATION,
1318 Tracer::LEVEL3,
|
1319 kumpf 1.94 "HTTPAuthenticatorDelegator - CIMExport: %s",
1320 cimOperation));
|
1321 marek 1.67
|
1322 thilo.boehm 1.77 MessageQueue* queue =
|
1323 kumpf 1.83 MessageQueue::lookup(_cimExportMessageQueueId);
|
1324 mike 1.2
|
1325 thilo.boehm 1.77 if (queue)
|
1326 mike 1.2 {
|
1327 thilo.boehm 1.77 httpMessage->dest = queue->getQueueId();
|
1328 mike 1.2
|
1329 thilo.boehm 1.77 queue->enqueue(httpMessage);
1330 deleteMessage = false;
|
1331 mike 1.2 }
|
1332 thilo.boehm 1.77 }
|
1333 kumpf 1.83 else if ((_wsmanOperationMessageQueueId != PEG_NOT_FOUND) &&
1334 ((requestUri == "/wsman") ||
1335 ((requestUri == "/wsman-anon") && !enableAuthentication)))
1336 {
1337 // Note: DSP0226 R5.3-1 specifies if /wsman is used,
1338 // unauthenticated access should not be allowed. This "should"
1339 // requirement is not implemented here, because it is difficult
1340 // for a client to determine whether enableAuthentication=true.
1341
1342 // DSP0226 R5.3-2 specifies if /wsman-anon is used, authenticated
1343 // access shall not be required. Unauthenticated access is
1344 // currently not allowed if enableAuthentication=true. When
1345 // support for wsmid:Identify is added, it will be necessary to
1346 // respond to that request without requiring authentication,
1347 // regardless of the CIM Server configuration.
1348
1349 MessageQueue* queue =
1350 MessageQueue::lookup(_wsmanOperationMessageQueueId);
1351
1352 if (queue)
1353 {
1354 kumpf 1.83 httpMessage->dest = queue->getQueueId();
1355
1356 try
1357 {
1358 queue->enqueue(httpMessage);
1359 }
1360 catch (const bad_alloc&)
1361 {
1362 delete httpMessage;
|
1363 venkat.puvvada 1.96 HTTPConnection *httpQueue =
1364 dynamic_cast<HTTPConnection*>(
1365 MessageQueue::lookup(queueId));
1366 if (httpQueue)
1367 {
1368 httpQueue->handleInternalServerError(0, true);
1369 }
|
1370 kumpf 1.83 PEG_METHOD_EXIT();
1371 deleteMessage = false;
1372 return;
1373 }
1374 deleteMessage = false;
1375 }
1376 }
|
1377 thilo.boehm 1.77 else
1378 {
1379 // We don't recognize this request message type
|
1380 david 1.21
|
1381 thilo.boehm 1.77 // The Specification for CIM Operations over HTTP reads:
1382 //
1383 // 3.3.4. CIMOperation
1384 //
1385 // If a CIM Server receives a CIM Operation request without
1386 // this [CIMOperation] header, it MUST NOT process it as if
1387 // it were a CIM Operation Request. The status code
1388 // returned by the CIM Server in response to such a request
1389 // is outside of the scope of this specification.
1390 //
1391 // 3.3.5. CIMExport
1392 //
1393 // If a CIM Listener receives a CIM Export request without
1394 // this [CIMExport] header, it MUST NOT process it. The
1395 // status code returned by the CIM Listener in response to
1396 // such a request is outside of the scope of this
1397 // specification.
1398 //
1399 // The author has chosen to send a 400 Bad Request error, but
1400 // without the CIMError header since this request must not be
1401 // processed as a CIM request.
1402 thilo.boehm 1.77
1403 _sendHttpError(
1404 queueId,
1405 HTTP_STATUS_BADREQUEST,
1406 String::EMPTY,
1407 String::EMPTY,
1408 closeConnect);
1409 PEG_METHOD_EXIT();
1410 return;
1411 } // bad request
1412 } // isRequestAuthenticated and enableAuthentication check
1413 else
1414 { // client not authenticated; send challenge
|
1415 gerarda 1.22 #ifdef PEGASUS_KERBEROS_AUTHENTICATION
|
1416 thilo.boehm 1.77 String authResp =
1417 _authenticationManager->getHttpAuthResponseHeader(
1418 httpMessage->authInfo);
|
1419 gerarda 1.22 #else
|
1420 thilo.boehm 1.77 String authResp =
1421 _authenticationManager->getHttpAuthResponseHeader();
|
1422 gerarda 1.22 #endif
|
1423 mike 1.2
|
1424 marek 1.100 if (authResp.size() > 0)
|
1425 thilo.boehm 1.77 {
|
1426 marek 1.100 if (authStatus.doChallenge())
1427 {
1428 _sendChallenge(
1429 queueId,
1430 authStatus.getErrorDetail(),
1431 authResp,
1432 closeConnect);
1433 }
1434 else
1435 {
1436 _sendHttpError(
1437 queueId,
1438 authStatus.getHttpStatus(),
1439 String::EMPTY,
1440 authStatus.getErrorDetail(),
1441 closeConnect);
1442 }
|
1443 thilo.boehm 1.77 }
1444 else
1445 {
1446 MessageLoaderParms msgParms(
1447 "Pegasus.Server.HTTPAuthenticatorDelegator."
1448 "AUTHORIZATION_HEADER_ERROR",
1449 "Authorization header error");
1450 String msg(MessageLoader::getMessage(msgParms));
1451 _sendHttpError(
1452 queueId,
1453 HTTP_STATUS_BADREQUEST,
1454 String::EMPTY,
1455 msg,
1456 closeConnect);
|
1457 mike 1.2 }
|
1458 thilo.boehm 1.77 }
|
1459 kumpf 1.11
|
1460 thilo.boehm 1.77 PEG_METHOD_EXIT();
|
1461 mike 1.2 }
1462
1463 PEGASUS_NAMESPACE_END
|