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