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