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