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 kumpf 1.6 throw PEGASUS_CIM_EXCEPTION( CIM_ERR_FAILED,
|
194 kumpf 1.3 "Timed out trying to perform requested operation."
195 "Please re-try the operation again.");
196 }
197 catch (WaitFailed e)
198 {
|
199 kumpf 1.6 throw PEGASUS_CIM_EXCEPTION( CIM_ERR_FAILED,
|
200 kumpf 1.3 "Timed out trying to perform requested operation."
201 "Please re-try the operation again.");
202 }
203 catch (Deadlock e)
204 {
|
205 kumpf 1.6 throw PEGASUS_CIM_EXCEPTION( CIM_ERR_FAILED,
|
206 kumpf 1.3 "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 kumpf 1.7 encryptedPassword = System::encryptPassword(password.getCString(),salt);
|
305 mike 1.2
|
306 kumpf 1.3 // add the user to the cache and password file
307 _Update(ADD_USER,userName, encryptedPassword);
|
308 mike 1.2
|
309 kumpf 1.5 PEG_METHOD_EXIT();
|
310 mike 1.2 }
311
312 //
313 // Modify user entry in file
314 //
315 void UserFileHandler::modifyUserEntry(
316 const String& userName,
317 const String& password,
318 const String& newPassword )
319 {
320 char salt[3];
321 String encryptedPassword = String::EMPTY;
322
|
323 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::modifyUserEntry");
|
324 mike 1.2
325 //
326 // Check if the given password matches the passwd in the file
327 //
328 try
329 {
330 if ( !verifyCIMUserPassword (userName,password) )
331 {
|
332 kumpf 1.5 PEG_METHOD_EXIT();
|
333 mike 1.2 throw PasswordMismatch(userName);
334 }
335 }
336 catch (Exception& e)
337 {
|
338 kumpf 1.5 PEG_METHOD_EXIT();
|
339 mike 1.2 throw e;
340 }
341
342 // encrypt new password
343 _GetSalt(salt);
344
|
345 kumpf 1.7 encryptedPassword = System::encryptPassword(newPassword.getCString(),salt);
|
346 mike 1.2
|
347 kumpf 1.3 _Update(MODIFY_USER, userName, encryptedPassword);
|
348 mike 1.2
|
349 kumpf 1.5 PEG_METHOD_EXIT();
|
350 mike 1.2 }
351
352 //
353 // Remove user entry from file
354 //
355 void UserFileHandler::removeUserEntry(const String& userName)
356 {
|
357 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::removeUserEntry");
|
358 mike 1.2
|
359 kumpf 1.3 _Update(REMOVE_USER, userName);
|
360 mike 1.2
|
361 kumpf 1.5 PEG_METHOD_EXIT();
|
362 mike 1.2 }
363
364 //
365 // Get a list of all the user names.
366 //
367 void UserFileHandler::getAllUserNames(Array<String>& userNames)
368 {
|
369 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::getAllUserNames");
|
370 mike 1.2
371 userNames.clear();
372
373 for (PasswordTable::Iterator i = _passwordTable.start(); i; i++)
374 {
375 userNames.append(i.key());
376 }
|
377 kumpf 1.5 PEG_METHOD_EXIT();
|
378 mike 1.2 }
379
380 //
381 // Verify whether the specified CIM user is valid
382 //
383 Boolean UserFileHandler::verifyCIMUser (const String& userName)
384 {
|
385 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER, "UserFileHandler::verifyCIMUser");
|
386 mike 1.2
|
387 kumpf 1.5 PEG_METHOD_EXIT();
|
388 mike 1.2 return _passwordTable.contains(userName);
389 }
390
391 //
392 // Verify whether the specified user's password is valid
393 //
394 Boolean UserFileHandler::verifyCIMUserPassword (
395 const String& userName,
396 const String& password)
397 {
|
398 kumpf 1.5 PEG_METHOD_ENTER(TRC_USER_MANAGER,
399 "UserFileHandler::verifyCIMUserPassword");
|
400 mike 1.2
401 // Check if the user's password mathches the specified password
402 String curPassword = String::EMPTY;
403 String encryptedPassword = String::EMPTY;
404 String saltStr = String::EMPTY;
405
406 // Check if the user exists in the password table
407 if ( !_passwordTable.lookup(userName,curPassword) )
408 {
|
409 kumpf 1.5 PEG_METHOD_EXIT();
|
410 mike 1.2 throw InvalidUser(userName);
411 }
412
413 saltStr = curPassword.subString(0,2);
414
415 encryptedPassword =
|
416 kumpf 1.7 System::encryptPassword(password.getCString(),saltStr.getCString());
|
417 mike 1.2
418 if ( curPassword != encryptedPassword )
419 {
|
420 kumpf 1.5 PEG_METHOD_EXIT();
|
421 mike 1.2 return false;
422 }
423
|
424 kumpf 1.5 PEG_METHOD_EXIT();
|
425 mike 1.2 return true;
426 }
427 PEGASUS_NAMESPACE_END
428
429
|