1 martin 1.56 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.57 //
|
3 martin 1.56 // 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.57 //
|
10 martin 1.56 // 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.57 //
|
17 martin 1.56 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.57 //
|
20 martin 1.56 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.57 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.56 // 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.57 //
|
28 martin 1.56 //////////////////////////////////////////////////////////////////////////
|
29 kumpf 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
|
32 sage 1.2 #include <Pegasus/Common/Config.h>
|
33 kumpf 1.9 #include <Pegasus/Common/Constants.h>
|
34 kumpf 1.1 #include <Pegasus/Security/UserManager/UserManager.h>
35 #include <Pegasus/Common/HTTPMessage.h>
36 #include <Pegasus/Common/XmlWriter.h>
37 #include <Pegasus/Common/Tracer.h>
|
38 kumpf 1.46 #include <Pegasus/Common/MessageLoader.h>
|
39 kumpf 1.1 #include "CIMOperationRequestAuthorizer.h"
|
40 kumpf 1.46
|
41 marek 1.42 #ifdef PEGASUS_ZOS_SECURITY
42 // This include file will not be provided in the OpenGroup CVS for now.
43 // Do NOT try to include it in your compile
|
44 kumpf 1.46 # include <Pegasus/Common/safCheckzOS_inline.h>
|
45 marek 1.42 #endif
|
46 kumpf 1.1
47 PEGASUS_NAMESPACE_BEGIN
48
49 PEGASUS_USING_STD;
50
|
51 kumpf 1.30 //
52 // Set group name separator
53 //
54 const char CIMOperationRequestAuthorizer::_GROUPNAME_SEPARATOR = ',';
|
55 kumpf 1.1
56 CIMOperationRequestAuthorizer::CIMOperationRequestAuthorizer(
|
57 kumpf 1.46 MessageQueueService* outputQueue)
58 : Base(PEGASUS_QUEUENAME_OPREQAUTHORIZER),
59 _outputQueue(outputQueue),
60 _serverTerminating(false)
|
61 kumpf 1.1 {
|
62 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER, "CIMOperationRequestAuthorizer::"
63 "CIMOperationRequestAuthorizer");
|
64 kumpf 1.1
|
65 kumpf 1.30 #ifdef PEGASUS_ENABLE_USERGROUP_AUTHORIZATION
|
66 kumpf 1.46 _authorizedUserGroups = _getAuthorizedUserGroups();
|
67 kumpf 1.30 #endif
68
|
69 kumpf 1.46 PEG_METHOD_EXIT();
|
70 kumpf 1.1 }
71
72 CIMOperationRequestAuthorizer::~CIMOperationRequestAuthorizer()
73 {
|
74 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER, "CIMOperationRequestAuthorizer::"
75 "~CIMOperationRequestAuthorizer");
|
76 kumpf 1.1
|
77 kumpf 1.46 PEG_METHOD_EXIT();
|
78 kumpf 1.1 }
79
80 void CIMOperationRequestAuthorizer::sendResponse(
|
81 kumpf 1.46 Uint32 queueId,
82 Buffer& message)
|
83 kumpf 1.1 {
|
84 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER, "CIMOperationRequestAuthorizer::sendResponse");
|
85 kumpf 1.1
|
86 kumpf 1.46 MessageQueue* queue = MessageQueue::lookup(queueId);
|
87 kumpf 1.1
|
88 kumpf 1.46 if (queue)
89 {
90 queue->enqueue(new HTTPMessage(message));
91 }
|
92 gerarda 1.27
|
93 kumpf 1.46 PEG_METHOD_EXIT();
|
94 kumpf 1.1 }
95
|
96 kumpf 1.7 // Code is duplicated in CIMOperationRequestDecoder
97 void CIMOperationRequestAuthorizer::sendIMethodError(
|
98 kumpf 1.46 Uint32 queueId,
99 HttpMethod httpMethod,
100 const String& messageId,
101 const CIMName& iMethodName,
102 const CIMException& cimException)
|
103 kumpf 1.1 {
|
104 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER,
105 "CIMOperationRequestAuthorizer::sendIMethodError");
|
106 kumpf 1.1
|
107 kumpf 1.46 Buffer message;
108 message = XmlWriter::formatSimpleIMethodErrorRspMessage(
109 iMethodName,
110 messageId,
111 httpMethod,
112 cimException);
|
113 kumpf 1.7
|
114 kumpf 1.46 sendResponse(queueId, message);
|
115 kumpf 1.1
|
116 kumpf 1.46 PEG_METHOD_EXIT();
|
117 kumpf 1.1 }
118
|
119 kumpf 1.23 // Code is duplicated in CIMOperationRequestDecoder
120 void CIMOperationRequestAuthorizer::sendMethodError(
|
121 kumpf 1.46 Uint32 queueId,
122 HttpMethod httpMethod,
123 const String& messageId,
124 const CIMName& methodName,
125 const CIMException& cimException)
|
126 kumpf 1.23 {
|
127 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER,
128 "CIMOperationRequestAuthorizer::sendMethodError");
|
129 kumpf 1.23
|
130 kumpf 1.46 Buffer message;
131 message = XmlWriter::formatSimpleMethodErrorRspMessage(
132 methodName,
133 messageId,
134 httpMethod,
135 cimException);
|
136 kumpf 1.23
|
137 kumpf 1.46 sendResponse(queueId, message);
|
138 kumpf 1.23
|
139 kumpf 1.46 PEG_METHOD_EXIT();
|
140 kumpf 1.23 }
141
|
142 kumpf 1.1 ////////////////////////////////////////////////////////////////////////////////
143
|
144 kumpf 1.46 void CIMOperationRequestAuthorizer::handleEnqueue(Message* request)
|
145 kumpf 1.1 {
146
|
147 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER,
148 "CIMOperationRequestAuthorizer::handleEnqueue");
|
149 kumpf 1.12
|
150 kumpf 1.46 if (!request)
151 {
|
152 kumpf 1.12 PEG_METHOD_EXIT();
153 return;
|
154 kumpf 1.46 }
155
156 AutoPtr<CIMOperationRequestMessage> req(
157 dynamic_cast<CIMOperationRequestMessage*>(request));
158
159 PEGASUS_ASSERT(req.get());
|
160 kumpf 1.12
|
161 kumpf 1.46 //
162 // Get the HTTPConnection queue id
163 //
164 QueueIdStack qis = req->queueIds.copyAndPop();
165
166 Uint32 queueId = qis.top();
167
168 // Set the client's requested language into this service thread.
169 // This will allow functions in this service to return messages
170 // in the correct language.
|
171 kumpf 1.53 req->updateThreadLanguages();
|
172 kumpf 1.46
173 //
174 // If CIMOM is shutting down, return "Service Unavailable" response
175 //
176 if (_serverTerminating)
177 {
178 Buffer message;
179 message = XmlWriter::formatHttpErrorRspMessage(
180 HTTP_STATUS_SERVICEUNAVAILABLE,
181 String::EMPTY,
182 "CIM Server is shutting down.");
183
184 sendResponse(queueId, message);
185 PEG_METHOD_EXIT();
186 return;
187 }
188
189 String userName = ((IdentityContainer)(req->operationContext.get(
190 IdentityContainer::NAME))).getUserName();
191 String authType = req->authType;
192 CIMNamespaceName nameSpace = req->nameSpace;
|
193 kumpf 1.51 String cimMethodName;
|
194 kumpf 1.46
195 switch (req->getType())
196 {
197 case CIM_GET_CLASS_REQUEST_MESSAGE:
198 cimMethodName = "GetClass";
199 break;
200
201 case CIM_GET_INSTANCE_REQUEST_MESSAGE:
202 cimMethodName = "GetInstance";
203 break;
204
205 case CIM_DELETE_CLASS_REQUEST_MESSAGE:
206 cimMethodName = "DeleteClass";
207 break;
208
209 case CIM_DELETE_INSTANCE_REQUEST_MESSAGE:
210 cimMethodName = "DeleteInstance";
211 break;
212
213 case CIM_CREATE_CLASS_REQUEST_MESSAGE:
214 cimMethodName = "CreateClass";
215 kumpf 1.46 break;
216
217 case CIM_CREATE_INSTANCE_REQUEST_MESSAGE:
218 cimMethodName = "CreateInstance";
219 break;
220
221 case CIM_MODIFY_CLASS_REQUEST_MESSAGE:
222 cimMethodName = "ModifyClass";
223 break;
224
225 case CIM_MODIFY_INSTANCE_REQUEST_MESSAGE:
226 cimMethodName = "ModifyInstance";
227 break;
228
229 case CIM_ENUMERATE_CLASSES_REQUEST_MESSAGE:
230 cimMethodName = "EnumerateClasses";
231 break;
232
233 case CIM_ENUMERATE_CLASS_NAMES_REQUEST_MESSAGE:
234 cimMethodName = "EnumerateClassNames";
235 break;
236 kumpf 1.46
237 case CIM_ENUMERATE_INSTANCES_REQUEST_MESSAGE:
238 cimMethodName = "EnumerateInstances";
239 break;
240
241 case CIM_ENUMERATE_INSTANCE_NAMES_REQUEST_MESSAGE:
242 cimMethodName = "EnumerateInstanceNames";
243 break;
244
245 case CIM_EXEC_QUERY_REQUEST_MESSAGE:
246 cimMethodName = "ExecQuery";
247 break;
248
249 case CIM_ASSOCIATORS_REQUEST_MESSAGE:
250 cimMethodName = "Associators";
251 break;
252
253 case CIM_ASSOCIATOR_NAMES_REQUEST_MESSAGE:
254 cimMethodName = "AssociatorNames";
255 break;
256
257 kumpf 1.46 case CIM_REFERENCES_REQUEST_MESSAGE:
258 cimMethodName = "References";
259 break;
260
261 case CIM_REFERENCE_NAMES_REQUEST_MESSAGE:
262 cimMethodName = "ReferenceNames";
263 break;
264
265 case CIM_GET_PROPERTY_REQUEST_MESSAGE:
266 cimMethodName = "GetProperty";
267 break;
268
269 case CIM_SET_PROPERTY_REQUEST_MESSAGE:
270 cimMethodName = "SetProperty";
271 break;
272
273 case CIM_GET_QUALIFIER_REQUEST_MESSAGE:
274 cimMethodName = "GetQualifier";
275 break;
276
277 case CIM_SET_QUALIFIER_REQUEST_MESSAGE:
278 kumpf 1.46 cimMethodName = "SetQualifier";
279 break;
280
281 case CIM_DELETE_QUALIFIER_REQUEST_MESSAGE:
282 cimMethodName = "DeleteQualifier";
283 break;
284
285 case CIM_ENUMERATE_QUALIFIERS_REQUEST_MESSAGE:
286 cimMethodName = "EnumerateQualifiers";
287 break;
288
289 case CIM_INVOKE_METHOD_REQUEST_MESSAGE:
290 cimMethodName = "InvokeMethod";
291 break;
292
293 default:
|
294 dl.meetei 1.58 PEGASUS_UNREACHABLE(PEGASUS_ASSERT(0);)
|
295 kumpf 1.46 break;
296 }
|
297 mday 1.5
|
298 marek 1.42 #ifdef PEGASUS_ZOS_SECURITY
|
299 kumpf 1.46 if (checkRequestTypeAuthorizationZOS(
300 req->getType(), userName, nameSpace) == false)
301 {
302 //
303 // user is not authorized, send an
304 // error message to the requesting client.
305 //
306 if (cimMethodName == "InvokeMethod")
307 {
308 sendMethodError(
309 queueId,
310 req->getHttpMethod(),
311 req->messageId,
312 ((CIMInvokeMethodRequestMessage*)req.get())->methodName,
313 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED,
314 MessageLoaderParms(
|
315 kumpf 1.50 "Server.CIMOperationRequestAuthorizer."
316 "NAMESPACE_AUTHORIZATION_FAILED",
317 "User '$0' is not authorized to run '$1' in the "
318 "namespace '$2'",
|
319 sushma.fernandes 1.47 userName, cimMethodName, nameSpace.getString())));
|
320 kumpf 1.46 }
321 else
322 {
323 sendIMethodError(
324 queueId,
325 req->getHttpMethod(),
326 req->messageId,
327 cimMethodName,
328 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED,
329 MessageLoaderParms(
|
330 kumpf 1.50 "Server.CIMOperationRequestAuthorizer."
331 "NAMESPACE_AUTHORIZATION_FAILED",
332 "User '$0' is not authorized to run '$1' in the "
333 "namespace '$2'",
|
334 sushma.fernandes 1.47 userName, cimMethodName, nameSpace.getString())));
|
335 kumpf 1.46 }
336 PEG_METHOD_EXIT();
337 return;
338 }
|
339 marek 1.42 #endif
340
|
341 kumpf 1.30 #ifdef PEGASUS_ENABLE_USERGROUP_AUTHORIZATION
|
342 kumpf 1.46 //
343 // If the user is not privileged and authorized user group is specified,
344 // then perform the user group authorization check.
345 //
346 try
347 {
348 if ( ! System::isPrivilegedUser(userName) )
349 {
350 Uint32 size = _authorizedUserGroups.size();
351
352 if (size > 0)
353 {
354 Boolean authorized = false;
355
356 //
357 // Check if the user name is in the authorized user groups.
358 //
359 for (Uint32 i = 0; i < size; i++)
360 {
361 //
362 // Check if the user is a member of the group
363 kumpf 1.46 //
364 if (System::isGroupMember(userName.getCString(),
365 _authorizedUserGroups[i].getCString()))
366 {
367 authorized = true;
368 break;
369 }
370 }
371
372 //
373 // If the user is not a member of any of the authorized
374 // user groups then generate error response.
375 //
376 if (!authorized)
377 {
|
378 thilo.boehm 1.55 PEG_TRACE((TRC_SERVER, Tracer::LEVEL1,
379 "Authorization Failed: User '%s' "
380 "is not a member of the authorized groups",
381 (const char*)userName.getCString()));
|
382 kumpf 1.46
383 MessageLoaderParms msgLoaderParms(
384 "Server.CIMOperationRequestAuthorizer."
385 "NOT_IN_AUTHORIZED_GRP",
386 "User '$0' is not authorized to access CIM data.",
387 userName);
388
389 //
390 // user is not in the authorized user groups, send an
391 // error message to the requesting client.
392 //
393 if (cimMethodName == "InvokeMethod")
394 {
395 sendMethodError(
396 queueId,
397 req->getHttpMethod(),
398 req->messageId,
399 ((CIMInvokeMethodRequestMessage*)req.get())->
400 methodName,
401 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED,
402 msgLoaderParms));
403 kumpf 1.46 PEG_METHOD_EXIT();
404 return;
405 }
406 else
407 {
408 sendIMethodError(
409 queueId,
410 req->getHttpMethod(),
411 req->messageId,
412 cimMethodName,
413 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED,
414 msgLoaderParms));
415 PEG_METHOD_EXIT();
416 return;
417 }
418 }
419 }
420 }
421 }
422 catch (InternalSystemError& ise)
423 {
424 kumpf 1.46 sendIMethodError(
425 queueId,
426 req->getHttpMethod(),
427 req->messageId,
428 cimMethodName,
429 PEGASUS_CIM_EXCEPTION(CIM_ERR_ACCESS_DENIED, ise.getMessage()));
430 PEG_METHOD_EXIT();
431 return;
432 }
|
433 kumpf 1.30 #endif // #ifdef PEGASUS_ENABLE_USERGROUP_AUTHORIZATION
434
|
435 kumpf 1.46 //
436 // Get a config manager instance
437 //
438 ConfigManager* configManager = ConfigManager::getInstance();
439
440 //
441 // Do namespace authorization verification
442 //
443 if (ConfigManager::parseBooleanValue(
444 configManager->getCurrentValue("enableNamespaceAuthorization")))
445 {
446 //
447 // If the user is not privileged, perform the authorization check.
448 //
449 if (!System::isPrivilegedUser(userName))
450 {
451 UserManager* userManager = UserManager::getInstance();
|
452 mday 1.5
|
453 kumpf 1.46 if (!userManager ||
454 !userManager->verifyAuthorization(
455 userName, nameSpace, cimMethodName))
456 {
457 if (cimMethodName == "InvokeMethod")
458 {
459 sendMethodError(
460 queueId,
461 req->getHttpMethod(),
462 req->messageId,
463 ((CIMInvokeMethodRequestMessage*)req.get())->methodName,
464 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED,
465 MessageLoaderParms(
|
466 kumpf 1.50 "Server.CIMOperationRequestAuthorizer."
467 "NAMESPACE_AUTHORIZATION_FAILED",
468 "User '$0' is not authorized to run '$1' in the "
469 "namespace '$2'",
470 userName, cimMethodName, nameSpace.getString())));
|
471 kumpf 1.46 }
472 else
473 {
474 sendIMethodError(
475 queueId,
476 req->getHttpMethod(),
477 req->messageId,
478 cimMethodName,
479 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED,
480 MessageLoaderParms(
|
481 kumpf 1.50 "Server.CIMOperationRequestAuthorizer."
482 "NAMESPACE_AUTHORIZATION_FAILED",
483 "User '$0' is not authorized to run '$1' in "
484 "the namespace '$2'",
485 userName,
486 cimMethodName,
487 nameSpace.getString())));
|
488 kumpf 1.46 }
|
489 kumpf 1.22
|
490 kumpf 1.46 PEG_METHOD_EXIT();
491 return;
|
492 kumpf 1.23 }
|
493 kumpf 1.46 }
494 }
|
495 mday 1.5
|
496 kumpf 1.46 //
497 // Enqueue the request
498 //
499 _outputQueue->enqueue(req.release());
|
500 kumpf 1.1
|
501 kumpf 1.46 PEG_METHOD_EXIT();
|
502 mday 1.5 }
503
504 void CIMOperationRequestAuthorizer::handleEnqueue()
505 {
|
506 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER,
507 "CIMOperationRequestAuthorizer::handleEnqueue");
|
508 kumpf 1.10
|
509 kumpf 1.46 Message* request = dequeue();
510 if (request)
511 handleEnqueue(request);
|
512 kumpf 1.10
|
513 kumpf 1.46 PEG_METHOD_EXIT();
|
514 kumpf 1.1 }
515
516 void CIMOperationRequestAuthorizer::setServerTerminating(Boolean flag)
517 {
|
518 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER,
519 "CIMOperationRequestAuthorizer::setServerTerminating");
|
520 kumpf 1.1
|
521 kumpf 1.46 _serverTerminating = flag;
|
522 kumpf 1.1
|
523 kumpf 1.46 PEG_METHOD_EXIT();
|
524 kumpf 1.1 }
525
|
526 kumpf 1.30 Array<String> CIMOperationRequestAuthorizer::_getAuthorizedUserGroups()
527 {
|
528 kumpf 1.46 PEG_METHOD_ENTER(TRC_SERVER,
529 "CIMOperationRequestAuthorizer::getAuthorizedUserGroups");
|
530 kumpf 1.30
|
531 kumpf 1.46 Array<String> authorizedGroups;
|
532 kumpf 1.30
|
533 kumpf 1.51 String groupNames;
|
534 kumpf 1.30
|
535 kumpf 1.46 //
536 // Get a config manager instance
537 //
538 ConfigManager* configManager = ConfigManager::getInstance();
539
540 groupNames = configManager->getCurrentValue("authorizedUserGroups");
541
542 //
543 // Check if the group name is empty
544 //
|
545 kumpf 1.51 if (groupNames == String::EMPTY)
|
546 kumpf 1.46 {
547 PEG_METHOD_EXIT();
548 return authorizedGroups;
549 }
550
551 //
552 // Append _GROUPNAME_SEPARATOR to the end of the groups
553 //
554 groupNames.append(_GROUPNAME_SEPARATOR);
555
556 Uint32 position = 0;
557 String groupName;
558
559 while (groupNames != String::EMPTY)
560 {
561 //
562 // Get a group name from user groups
563 // User groups are separated by _GROUPNAME_SEPARATOR
564 //
565 position = groupNames.find(_GROUPNAME_SEPARATOR);
566 groupName = groupNames.subString(0,(position));
567 kumpf 1.46
568 authorizedGroups.append(groupName);
569
570 // Remove the searched group name
571 groupNames.remove(0, position + 1);
572 }
|
573 kumpf 1.30
|
574 kumpf 1.46 PEG_METHOD_EXIT();
|
575 kumpf 1.30
|
576 kumpf 1.46 return authorizedGroups;
577 }
|
578 kumpf 1.30
|
579 kumpf 1.1 PEGASUS_NAMESPACE_END
|