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