1 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // 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 // 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 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // 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 // 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 // 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 mike 1.2 //==============================================================================
23 //
24 // Author: Sushma Fernandes, Hewlett Packard Company (sushma_fernandes@hp.com)
25 //
26 // Modified By:
27 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30
31 #include <cctype>
32 #include <fstream>
33
34 #include <Pegasus/Common/FileSystem.h>
35 #include <Pegasus/Common/Destroyer.h>
36 #include <Pegasus/Common/Logger.h>
37 #include <Pegasus/Common/Tracer.h>
38
39 #include <Pegasus/Security/UserManager/PasswordFile.h>
40 #include <Pegasus/Security/UserManager/UserExceptions.h>
41
42
43 mike 1.2 PEGASUS_USING_STD;
44
45 PEGASUS_NAMESPACE_BEGIN
46
47 const char COLON = ':';
48
49 /*
50 Password file header information
51 */
52 static const char* PasswordFileHeader [] = {
53 "########################################################################",
54 "## ##",
55 "## CIM Server Password file ##",
56 "## ##",
57 "########################################################################",
58 " ",
59 "########################################################################",
60 "# #",
61 "# This is the password file for the CIMOM. The username/passowrd #",
62 "# in this file are loaded in to CIMOM by the User Manager Provider. #",
63 "# CIMOM updates this file with the changes . #",
64 mike 1.2 "# #",
65 "# The password file stores the user information in username:password #",
66 "# format in order to be compatible with Apache's htpasswd generated #",
67 "# password file. #",
68 "# #",
69 "# The user must not edit this file, instead use #",
70 "# cimuser CLI to make any changes to the CIMOM user information. #",
71 "# #",
72 "########################################################################",
73 " "
74 };
75
76 static const int HEADER_SIZE = sizeof(PasswordFileHeader)/sizeof(PasswordFileHeader[0]);
77
78
79 ////////////////////////////////////////////////////////////////////////////////
80 //
81 // PasswordFile Class
82 //
83 ////////////////////////////////////////////////////////////////////////////////
84
85 mike 1.2
86
87 /**
88 Constructor.
89 */
90 PasswordFile::PasswordFile (const String& fileName)
91 {
92 const char METHOD_NAME[] = "PasswordFile::PasswordFile";
93 PEG_FUNC_ENTER(TRC_USER_MANAGER,METHOD_NAME);
94
95 _passwordFile = fileName;
96
97 _passwordBackupFile = fileName + ".bak";
98
|
99 kumpf 1.3 try
100 {
101 PasswordTable pt;
102 load(pt);
103 }
104 catch( NoSuchFile& e )
|
105 mike 1.2 {
|
106 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::SEVERE,
107 "Password file not found : $0.", _passwordFile);
108 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
109 "Creating blank password file.");
|
110 mike 1.2 PasswordTable pt;
111 save(pt);
112 }
|
113 kumpf 1.3 catch ( Exception& e)
114 {
115 throw e;
116 }
|
117 mike 1.2 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
118 }
119
120 /**
121 Destructor.
122 */
123 PasswordFile::~PasswordFile ()
124 {
125 const char METHOD_NAME[] = "PasswordFile::~PasswordFile";
126 PEG_FUNC_ENTER(TRC_USER_MANAGER,METHOD_NAME);
127
128 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
129 }
130
131 /**
132 Load the username and password from the password file.
133 */
134 void PasswordFile::load (PasswordTable& passwordTable)
135 {
136 String line;
137 const char METHOD_NAME[] = "PasswordFile::load";
138 mike 1.2
139 PEG_FUNC_ENTER(TRC_USER_MANAGER,METHOD_NAME);
140
|
141 kumpf 1.3 //
142 // Check if the backup file exists, if it does use the backup file
143 // If not try to use the password file
144 //
145 if (FileSystem::exists(_passwordBackupFile))
146 {
147 if (FileSystem::exists(_passwordFile))
148 {
149 if (! FileSystem::removeFile(_passwordFile))
150 {
151 throw CannotRemoveFile(_passwordFile);
152 }
153 }
154 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
155 "Trying to use the backup file : $0.", _passwordBackupFile);
156 if (! FileSystem::renameFile(_passwordBackupFile, _passwordFile))
157 {
158 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
159 "Unable to use the backup file : $0.", _passwordBackupFile);
160 throw CannotRenameFile(_passwordBackupFile);
161 }
162 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
163 "Recovered using the backup file : $0.", _passwordBackupFile);
164 }
165 if (! FileSystem::exists(_passwordFile))
166 {
167 throw NoSuchFile(_passwordFile);
168 }
169
|
170 mike 1.2 //
171 // Open the password file
172 //
173 ArrayDestroyer<char> p(_passwordFile.allocateCString());
174 ifstream ifs(p.getPointer());
175 if (!ifs)
176 {
|
177 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::SEVERE,
178 "Error opening password file : $0.", _passwordFile);
179 return;
|
180 mike 1.2 }
181
182 //
183 // Read each line of the file
184 //
185 for (Uint32 lineNumber = 1; GetLine(ifs, line); lineNumber++)
186 {
187 // Get the userName and password
188
189 //
190 // Skip leading whitespace
191 //
192 const Char16* p = line.getData();
193
194 while (*p && isspace(*p))
195 {
196 p++;
197 }
198
199 if (!*p)
200 {
201 mike 1.2 continue;
202 }
203
204 //
205 // Skip comment lines
206 //
207 if (*p == '#')
208 {
209 continue;
210 }
211
212 //
213 // Get the userName
214 //
215 String userName = String::EMPTY;
216
217 userName += *p++;
218
219 while (isalnum(*p))
220 {
221 userName += *p++;
222 mike 1.2 }
223
224 //
225 // Skip whitespace after user name
226 //
227 while (*p && isspace(*p))
228 {
229 p++;
230 }
231
232 //
233 // Expect a colon sign
234 //
235 if (*p != COLON)
236 {
237 //
238 // Did not find Colon, log a message and skip entry
239 //
240 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
|
241 kumpf 1.3 "Error in reading password entry for : $0.", userName);
|
242 mike 1.2 continue;
243 }
244
245 p++;
246
247 //
248 // Skip whitespace after : sign
249 //
250 while (*p && isspace(*p))
251 {
252 p++;
253 }
254
255 //
256 // Get the password
257 //
258 String password = String::EMPTY;
259
260 while (*p)
261 {
262 password += *p++;
263 mike 1.2 }
264
265 //
266 // Store the user name and password in the table
267 //
268 if (!passwordTable.insert(userName, password))
269 {
270 //
271 // Duplicate entry for user, ignore the new entry.
272 //
273 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
|
274 kumpf 1.3 "Duplicate user: $0.", userName);
|
275 mike 1.2 }
276 }
277
278 ifs.close();
279 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
280 }
281
282
283 /**
284 Save the username and password to the password file.
285 */
286 void PasswordFile::save (PasswordTable& passwordTable)
287 {
288 const char METHOD_NAME[] = "PasswordFile::save";
289
290 PEG_FUNC_ENTER(TRC_USER_MANAGER, METHOD_NAME);
291
292 //
|
293 kumpf 1.3 // Check if backup password file exists, if it does remove the password file
294 // If it does not rename the password file to password backup file
|
295 mike 1.2 //
296 if (FileSystem::exists(_passwordBackupFile))
297 {
|
298 kumpf 1.3 if ( FileSystem::exists(_passwordFile))
|
299 mike 1.2 {
|
300 kumpf 1.3 if ( ! FileSystem::removeFile(_passwordFile))
301 {
302 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::SEVERE,
303 "Cannot remove password file : $0.", _passwordFile);
304 throw CannotRemoveFile(_passwordFile);
305 }
|
306 mike 1.2 }
307 }
|
308 kumpf 1.3 else
|
309 mike 1.2 {
|
310 kumpf 1.3 if ( FileSystem::exists(_passwordFile))
|
311 mike 1.2 {
|
312 kumpf 1.3 if ( ! FileSystem::renameFile(_passwordFile, _passwordBackupFile))
313 {
314 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::SEVERE,
315 "Cannot rename password file : $0.", _passwordFile);
316 throw CannotRenameFile(_passwordFile);
317 }
|
318 mike 1.2 }
319 }
320
321 //
|
322 kumpf 1.3 // Open the password file for writing
|
323 mike 1.2 //
|
324 kumpf 1.3 ArrayDestroyer<char> p(_passwordFile.allocateCString());
|
325 mike 1.2 ofstream ofs(p.getPointer());
326 if (!ofs)
327 {
328 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
329 throw CannotOpenFile(getFileName());
330 }
331
332 ofs.clear();
333
334 //
335 // Write password file header information
336 //
337
338 for (int index = 0; index < HEADER_SIZE; index++)
339 {
340 ofs << PasswordFileHeader[index] << endl;
341 }
342
343 ofs << endl;
344
345 //
346 mike 1.2 // Save user names and passwords to the new file
347 //
348 for (PasswordTable::Iterator i = passwordTable.start(); i; i++)
349 {
350 ofs << i.key() << ":" << i.value() << endl;
351 }
352
353 ofs.close();
354
|
355 kumpf 1.3 if ( FileSystem::exists(_passwordBackupFile))
|
356 mike 1.2 {
|
357 kumpf 1.3 if ( ! FileSystem::removeFile(_passwordBackupFile))
|
358 mike 1.2 {
|
359 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "CIMPassword",
360 Logger::SEVERE,
361 "Cannot remove backup password file : $0.",
362 _passwordBackupFile);
363 throw CannotRemoveFile(_passwordBackupFile);
|
364 mike 1.2 }
365 }
366 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
367 }
368
369 PEGASUS_NAMESPACE_END
370
|