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