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