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