1 karl 1.21 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.16 // 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.12 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.16 // 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.19 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.21 // 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.4 // 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 karl 1.21 //
|
21 kumpf 1.4 // 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.4 // 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 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
|
30 kumpf 1.4 //==============================================================================
|
31 mike 1.2 //
32 // Author: Sushma Fernandes, Hewlett Packard Company (sushma_fernandes@hp.com)
33 //
34 // Modified By:
|
35 a.arora 1.14 // Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
|
36 a.arora 1.17 // Josephine Eskaline Joyce (jojustin@in.ibm.com) for PEP#101
|
37 joyce.j 1.18 // Josephine Eskaline Joyce (jojustin@in.ibm.com) for Bug#2486
|
38 david.dillard 1.20 // David Dillard, VERITAS Software Corp.
39 // (david.dillard@veritas.com)
|
40 mike 1.2 //
41 //%////////////////////////////////////////////////////////////////////////////
42
43
44 ///////////////////////////////////////////////////////////////////////////////
|
45 david.dillard 1.20 //
46 // This file implements the functionality required to manage password file.
|
47 mike 1.2 //
48 ///////////////////////////////////////////////////////////////////////////////
49
50 #include <Pegasus/Common/FileSystem.h>
51 #include <Pegasus/Common/Logger.h>
52 #include <Pegasus/Common/System.h>
53 #include <Pegasus/Common/Tracer.h>
|
54 mike 1.22 #include <Pegasus/Common/IPCExceptions.h>
|
55 mike 1.2
|
56 kumpf 1.3 #include <Pegasus/Config/ConfigManager.h>
57
|
58 mike 1.2 #include <Pegasus/Security/UserManager/UserFileHandler.h>
59 #include <Pegasus/Security/UserManager/UserExceptions.h>
|
60 humberto 1.9 #include <Pegasus/Common/MessageLoader.h> //l10n
|
61 mike 1.2
62 PEGASUS_USING_STD;
63
64 PEGASUS_NAMESPACE_BEGIN
65
|
66 david.dillard 1.20 const unsigned char UserFileHandler::_SALT_STRING[] =
|
67 mike 1.2 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
68
|
69 david.dillard 1.20 const String UserFileHandler::_PROPERTY_NAME_PASSWORD_FILEPATH =
70 "passwordFilePath";
|
71 kumpf 1.3
72 // Initialize the mutex timeout to 5000 ms.
73 const Uint32 UserFileHandler::_MUTEX_TIMEOUT = 5000;
74
|
75 mike 1.2 //
76 // Generate random salt key for password encryption refer to crypt(3C)
77 //
78 void UserFileHandler::_GetSalt(char *salt)
79 {
80 long randNum;
81 Uint32 sec;
82 Uint32 milliSec;
83
|
84 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "PasswordFile::_GetSalt");
|
85 mike 1.2
86 //
|
87 david.dillard 1.20 // Generate a random number and get the salt
|
88 mike 1.2 //
89 System::getCurrentTime( sec, milliSec );
90
91 srand( (int) sec );
|
92 keith.petley 1.10 #ifdef PEGASUS_PLATFORM_SOLARIS_SPARC
93 Unit32 seed;
94 randNum = rand_r(*seed);
95 #else
|
96 mike 1.2 randNum = rand();
|
97 keith.petley 1.10 #endif
|
98 mike 1.2
99 //
|
100 david.dillard 1.20 // Make sure the random number generated is between 0-63.
|
101 mike 1.2 // refer to _SALT_STRING variable
102 //
103 *salt++ = _SALT_STRING[ randNum & 0x3f ];
104 randNum >>= 6;
105 *salt++ = _SALT_STRING[ randNum & 0x3f ];
106
|
107 s.hills 1.11 *salt = '\0';
|
108 mike 1.2
|
109 kumpf 1.5 PEG_METHOD_EXIT();
|
110 mike 1.2 }
111
112 //
|
113 david.dillard 1.20 // Constructor.
|
114 mike 1.2 //
115 UserFileHandler::UserFileHandler()
116 {
|
117 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::UserFileHandler");
|
118 mike 1.2
|
119 kumpf 1.3 //
120 // Get an instance of the ConfigManager.
121 //
|
122 joyce.j 1.18 ConfigManager* configManager;
123 configManager = ConfigManager::getInstance();
|
124 mike 1.2
|
125 kumpf 1.3 //
126 // Get the PasswordFilePath property from the Config Manager.
127 //
128 String passwdFile;
|
129 kumpf 1.15 passwdFile = ConfigManager::getHomedPath(
130 configManager->getCurrentValue(_PROPERTY_NAME_PASSWORD_FILEPATH));
|
131 mike 1.2
|
132 kumpf 1.3 //
133 // Construct a PasswordFile object.
134 //
|
135 a.arora 1.14 _passwordFile.reset(new PasswordFile(passwdFile));
|
136 mike 1.2
137 //
|
138 kumpf 1.3 // Load the user information in to the cache.
|
139 mike 1.2 //
140 try
141 {
142 _loadAllUsers();
143 }
|
144 david.dillard 1.20 catch (const Exception&)
|
145 mike 1.2 {
|
146 david.dillard 1.20 throw;
|
147 mike 1.2 }
148
|
149 kumpf 1.3 //
150 // Initialize the mutex, mutex lock needs to be held for any updates
151 // to the password cache and password file.
152 //
|
153 a.arora 1.14 _mutex.reset(new Mutex);
|
154 kumpf 1.3
|
155 kumpf 1.5 PEG_METHOD_EXIT();
|
156 mike 1.2 }
157
158
159 //
|
160 david.dillard 1.20 // Destructor.
|
161 mike 1.2 //
162 UserFileHandler::~UserFileHandler()
163 {
|
164 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::~UserFileHandler");
|
165 mike 1.2
|
166 kumpf 1.5 PEG_METHOD_EXIT();
|
167 mike 1.2 }
168
|
169 david.dillard 1.20 //
|
170 mike 1.2 // Load all user names and password
171 //
172 void UserFileHandler::_loadAllUsers ()
173 {
|
174 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::_loadAllUsers");
|
175 mike 1.2
176 try
177 {
178 _passwordTable.clear();
179 _passwordFile->load(_passwordTable);
180 }
|
181 kumpf 1.13 catch (CannotOpenFile&)
|
182 mike 1.2 {
183 _passwordTable.clear();
|
184 kumpf 1.5 PEG_METHOD_EXIT();
|
185 kumpf 1.13 throw;
|
186 mike 1.2 }
|
187 kumpf 1.5 PEG_METHOD_EXIT();
|
188 mike 1.2 }
189
|
190 kumpf 1.3 void UserFileHandler::_Update(
191 char operation,
192 const String& userName,
193 const String& password)
194 {
|
195 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::_Update");
|
196 kumpf 1.3
197 //
198 // Hold the mutex lock.
199 // This will allow any one of the update operations to be performed
200 // at any given time
201 //
202
203 try
204 {
|
205 mike 1.22 _mutex->timed_lock(_MUTEX_TIMEOUT);
|
206 kumpf 1.3 }
|
207 kumpf 1.13 catch (TimeOut&)
|
208 kumpf 1.3 {
|
209 humberto 1.9 //l10n
|
210 david.dillard 1.20 //throw PEGASUS_CIM_EXCEPTION( CIM_ERR_FAILED,
|
211 humberto 1.9 //"Timed out trying to perform requested operation."
212 //"Please re-try the operation again.");
213 throw PEGASUS_CIM_EXCEPTION_L( CIM_ERR_FAILED, MessageLoaderParms("Security.UserManager.UserFileHandler.TIMEOUT",
214 "Timed out trying to perform requested operation.Please re-try the operation again."));
|
215 kumpf 1.3 }
|
216 kumpf 1.13 catch (WaitFailed&)
|
217 kumpf 1.3 {
|
218 humberto 1.9 //l10n
|
219 david.dillard 1.20 //throw PEGASUS_CIM_EXCEPTION( CIM_ERR_FAILED,
|
220 humberto 1.9 //"Timed out trying to perform requested operation."
221 //"Please re-try the operation again.");
222 throw PEGASUS_CIM_EXCEPTION_L( CIM_ERR_FAILED, MessageLoaderParms("Security.UserManager.UserFileHandler.TIMEOUT",
223 "Timed out trying to perform requested operation.Please re-try the operation again."));
|
224 kumpf 1.3 }
|
225 kumpf 1.13 catch (Deadlock&)
|
226 kumpf 1.3 {
|
227 humberto 1.9 //l10n
|
228 david.dillard 1.20 //throw PEGASUS_CIM_EXCEPTION( CIM_ERR_FAILED,
|
229 humberto 1.9 //"Deak lock encountered trying to perform requested operation."
230 //"Please re-try the operation again.");
231 throw PEGASUS_CIM_EXCEPTION_L( CIM_ERR_FAILED, MessageLoaderParms("Security.UserManager.UserFileHandler.DEADLOCK",
232 "Deak lock encountered trying to perform requested operation.Please re-try the operation again."));
|
233 kumpf 1.3 }
234
235 switch (operation)
236 {
237 case ADD_USER:
238 if (!_passwordTable.insert(userName,password))
239 {
240 _mutex->unlock();
|
241 kumpf 1.5 PEG_METHOD_EXIT();
|
242 kumpf 1.3 throw PasswordCacheError();
243 }
|
244 david.dillard 1.20 break;
|
245 kumpf 1.3
246 case MODIFY_USER:
247 if (!_passwordTable.remove(userName))
248 {
249 _mutex->unlock();
|
250 kumpf 1.5 PEG_METHOD_EXIT();
|
251 kumpf 1.3 throw PasswordCacheError();
252 }
253 if (!_passwordTable.insert(userName,password))
254 {
255 _mutex->unlock();
|
256 humberto 1.9 //l10n
|
257 david.dillard 1.20 //Logger::put(Logger::ERROR_LOG, System::CIMSERVER,
258 //Logger::SEVERE,
|
259 humberto 1.9 //"Error updating user information for : $0.",userName);
|
260 david.dillard 1.20 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER,Logger::SEVERE,
|
261 humberto 1.9 "Security.UserManager.UserFileHandler.ERROR_UPDATING_USER_INFO",
262 "Error updating user information for : $0.",userName);
|
263 kumpf 1.5 PEG_METHOD_EXIT();
|
264 kumpf 1.3 throw PasswordCacheError();
265 }
|
266 david.dillard 1.20 break;
|
267 kumpf 1.3
268 case REMOVE_USER:
269
270 //Remove the existing user name and password from the table
271 if (!_passwordTable.remove(userName))
272 {
273 _mutex->unlock();
|
274 kumpf 1.5 PEG_METHOD_EXIT();
|
275 kumpf 1.3 throw InvalidUser(userName);
276 }
|
277 david.dillard 1.20 break;
278
|
279 kumpf 1.3 default:
280 // Should never get here
281 break;
282 }
|
283 david.dillard 1.20
|
284 kumpf 1.3 // Store the entry in the password file
285 try
286 {
287 _passwordFile->save(_passwordTable);
288 }
|
289 david.dillard 1.20 catch (const CannotOpenFile&)
|
290 kumpf 1.3 {
291 _mutex->unlock();
|
292 kumpf 1.5 PEG_METHOD_EXIT();
|
293 david.dillard 1.20 throw;
|
294 kumpf 1.3 }
|
295 david.dillard 1.20 catch (const CannotRenameFile&)
|
296 kumpf 1.3 {
297 //
298 // reload password hash table from file
299 //
300 _loadAllUsers();
301
302 _mutex->unlock();
|
303 kumpf 1.5 PEG_METHOD_EXIT();
|
304 david.dillard 1.20 throw;
|
305 kumpf 1.3 }
306 _mutex->unlock();
|
307 kumpf 1.5 PEG_METHOD_EXIT();
|
308 kumpf 1.3 }
309
310
|
311 david.dillard 1.20 //
|
312 mike 1.2 // Add user entry to file
|
313 david.dillard 1.20 //
|
314 mike 1.2 void UserFileHandler::addUserEntry(
|
315 david.dillard 1.20 const String& userName,
|
316 mike 1.2 const String& password)
317 {
318 char salt[3];
319 String encryptedPassword = String::EMPTY;
320
|
321 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::addUserEntry");
|
322 mike 1.2
323 // Check if the user already exists
324 if (_passwordTable.contains(userName))
325 {
|
326 kumpf 1.5 PEG_METHOD_EXIT();
|
327 mike 1.2 throw DuplicateUser(userName);
328 }
329
330 // encrypt password
331 _GetSalt(salt);
332
|
333 kumpf 1.7 encryptedPassword = System::encryptPassword(password.getCString(),salt);
|
334 mike 1.2
|
335 kumpf 1.3 // add the user to the cache and password file
336 _Update(ADD_USER,userName, encryptedPassword);
|
337 mike 1.2
|
338 kumpf 1.5 PEG_METHOD_EXIT();
|
339 mike 1.2 }
340
|
341 david.dillard 1.20 //
342 // Modify user entry in file
|
343 mike 1.2 //
344 void UserFileHandler::modifyUserEntry(
345 const String& userName,
346 const String& password,
347 const String& newPassword )
348 {
349 char salt[3];
350 String encryptedPassword = String::EMPTY;
351
|
352 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::modifyUserEntry");
|
353 mike 1.2
354 //
355 // Check if the given password matches the passwd in the file
356 //
357 try
358 {
359 if ( !verifyCIMUserPassword (userName,password) )
360 {
|
361 kumpf 1.5 PEG_METHOD_EXIT();
|
362 david.dillard 1.20 throw PasswordMismatch(userName);
|
363 mike 1.2 }
364 }
|
365 david.dillard 1.20 catch (const Exception&)
|
366 mike 1.2 {
|
367 kumpf 1.5 PEG_METHOD_EXIT();
|
368 david.dillard 1.20 throw;
|
369 mike 1.2 }
370
371 // encrypt new password
372 _GetSalt(salt);
373
|
374 kumpf 1.7 encryptedPassword = System::encryptPassword(newPassword.getCString(),salt);
|
375 mike 1.2
|
376 kumpf 1.3 _Update(MODIFY_USER, userName, encryptedPassword);
|
377 mike 1.2
|
378 kumpf 1.5 PEG_METHOD_EXIT();
|
379 mike 1.2 }
380
|
381 david.dillard 1.20 //
382 // Remove user entry from file
383 //
|
384 mike 1.2 void UserFileHandler::removeUserEntry(const String& userName)
385 {
|
386 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::removeUserEntry");
|
387 mike 1.2
|
388 kumpf 1.3 _Update(REMOVE_USER, userName);
|
389 mike 1.2
|
390 kumpf 1.5 PEG_METHOD_EXIT();
|
391 mike 1.2 }
392
393 //
394 // Get a list of all the user names.
395 //
396 void UserFileHandler::getAllUserNames(Array<String>& userNames)
397 {
|
398 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::getAllUserNames");
|
399 mike 1.2
400 userNames.clear();
401
402 for (PasswordTable::Iterator i = _passwordTable.start(); i; i++)
403 {
404 userNames.append(i.key());
405 }
|
406 kumpf 1.5 PEG_METHOD_EXIT();
|
407 mike 1.2 }
408
409 //
410 // Verify whether the specified CIM user is valid
411 //
412 Boolean UserFileHandler::verifyCIMUser (const String& userName)
413 {
|
414 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::verifyCIMUser");
|
415 mike 1.2
|
416 kumpf 1.5 PEG_METHOD_EXIT();
|
417 mike 1.2 return _passwordTable.contains(userName);
418 }
419
420 //
421 // Verify whether the specified user's password is valid
422 //
423 Boolean UserFileHandler::verifyCIMUserPassword (
|
424 david.dillard 1.20 const String& userName,
|
425 mike 1.2 const String& password)
426 {
|
427 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER,
428 "UserFileHandler::verifyCIMUserPassword");
|
429 mike 1.2
430 // Check if the user's password mathches the specified password
431 String curPassword = String::EMPTY;
432 String encryptedPassword = String::EMPTY;
433 String saltStr = String::EMPTY;
434
435 // Check if the user exists in the password table
436 if ( !_passwordTable.lookup(userName,curPassword) )
437 {
|
438 kumpf 1.5 PEG_METHOD_EXIT();
|
439 mike 1.2 throw InvalidUser(userName);
440 }
441
442 saltStr = curPassword.subString(0,2);
443
444 encryptedPassword =
|
445 kumpf 1.7 System::encryptPassword(password.getCString(),saltStr.getCString());
|
446 mike 1.2
447 if ( curPassword != encryptedPassword )
448 {
|
449 kumpf 1.5 PEG_METHOD_EXIT();
|
450 mike 1.2 return false;
451 }
452
|
453 kumpf 1.5 PEG_METHOD_EXIT();
|
454 mike 1.2 return true;
455 }
456 PEGASUS_NAMESPACE_END
457
458
|