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