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