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