1 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
2 //
|
3 kumpf 1.6 // 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 // 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 kumpf 1.6 //
|
13 mike 1.2 // 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 //==============================================================================
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 mike 1.2 #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 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 mike 1.2 "## 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 "# #",
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 mike 1.2 static const int HEADER_SIZE = sizeof(PasswordFileHeader)/sizeof(PasswordFileHeader[0]);
77
78
79 ////////////////////////////////////////////////////////////////////////////////
80 //
81 // PasswordFile Class
82 //
83 ////////////////////////////////////////////////////////////////////////////////
84
85
86
87 /**
88 Constructor.
89 */
90 PasswordFile::PasswordFile (const String& fileName)
91 {
|
92 kumpf 1.7 PEG_METHOD_ENTER(TRC_USER_MANAGER, "PasswordFile::PasswordFile");
|
93 mike 1.2
94 _passwordFile = fileName;
95
96 _passwordBackupFile = fileName + ".bak";
97
|
98 kumpf 1.3 try
99 {
100 PasswordTable pt;
101 load(pt);
102 }
103 catch( NoSuchFile& e )
|
104 mike 1.2 {
|
105 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::SEVERE,
106 "Password file not found : $0.", _passwordFile);
107 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
108 "Creating blank password file.");
|
109 mike 1.2 PasswordTable pt;
110 save(pt);
111 }
|
112 kumpf 1.3 catch ( Exception& e)
113 {
114 throw e;
115 }
|
116 kumpf 1.7 PEG_METHOD_EXIT();
|
117 mike 1.2 }
118
119 /**
120 Destructor.
121 */
122 PasswordFile::~PasswordFile ()
123 {
|
124 kumpf 1.7 PEG_METHOD_ENTER(TRC_USER_MANAGER, "PasswordFile::~PasswordFile");
|
125 mike 1.2
|
126 kumpf 1.7 PEG_METHOD_EXIT();
|
127 mike 1.2 }
128
129 /**
130 Load the username and password from the password file.
131 */
132 void PasswordFile::load (PasswordTable& passwordTable)
133 {
134 String line;
135
|
136 kumpf 1.7 PEG_METHOD_ENTER(TRC_USER_MANAGER, "PasswordFile::load");
|
137 mike 1.2
|
138 kumpf 1.3 //
139 // Check if the backup file exists, if it does use the backup file
140 // If not try to use the password file
141 //
142 if (FileSystem::exists(_passwordBackupFile))
143 {
144 if (FileSystem::exists(_passwordFile))
145 {
146 if (! FileSystem::removeFile(_passwordFile))
147 {
148 throw CannotRemoveFile(_passwordFile);
149 }
150 }
151 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
152 "Trying to use the backup file : $0.", _passwordBackupFile);
153 if (! FileSystem::renameFile(_passwordBackupFile, _passwordFile))
154 {
155 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
156 "Unable to use the backup file : $0.", _passwordBackupFile);
157 throw CannotRenameFile(_passwordBackupFile);
158 }
159 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::INFORMATION,
160 "Recovered using the backup file : $0.", _passwordBackupFile);
161 }
162 if (! FileSystem::exists(_passwordFile))
163 {
164 throw NoSuchFile(_passwordFile);
165 }
166
|
167 mike 1.2 //
168 // Open the password file
169 //
170 ArrayDestroyer<char> p(_passwordFile.allocateCString());
171 ifstream ifs(p.getPointer());
172 if (!ifs)
173 {
|
174 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "UserManager", Logger::SEVERE,
175 "Error opening password file : $0.", _passwordFile);
176 return;
|
177 mike 1.2 }
178
179 //
180 // Read each line of the file
181 //
182 for (Uint32 lineNumber = 1; GetLine(ifs, line); lineNumber++)
183 {
184 // Get the userName and password
185
186 //
187 // Skip leading whitespace
188 //
189 const Char16* p = line.getData();
190
191 while (*p && isspace(*p))
192 {
193 p++;
194 }
195
196 if (!*p)
197 {
198 mike 1.2 continue;
199 }
200
201 //
202 // Skip comment lines
203 //
204 if (*p == '#')
205 {
206 continue;
207 }
208
209 //
210 // Get the userName
211 //
212 String userName = String::EMPTY;
213
|
214 kumpf 1.8 userName.append(*p++);
|
215 mike 1.2
216 while (isalnum(*p))
217 {
|
218 kumpf 1.8 userName.append(*p++);
|
219 mike 1.2 }
220
221 //
222 // Skip whitespace after user name
223 //
224 while (*p && isspace(*p))
225 {
226 p++;
227 }
228
229 //
230 // Expect a colon sign
231 //
232 if (*p != COLON)
233 {
234 //
235 // Did not find Colon, log a message and skip entry
236 //
237 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
|
238 kumpf 1.3 "Error in reading password entry for : $0.", userName);
|
239 mike 1.2 continue;
240 }
241
242 p++;
243
244 //
245 // Skip whitespace after : sign
246 //
247 while (*p && isspace(*p))
248 {
249 p++;
250 }
251
252 //
253 // Get the password
254 //
255 String password = String::EMPTY;
256
257 while (*p)
258 {
|
259 kumpf 1.8 password.append(*p++);
|
260 mike 1.2 }
261
262 //
263 // Store the user name and password in the table
264 //
265 if (!passwordTable.insert(userName, password))
266 {
267 //
268 // Duplicate entry for user, ignore the new entry.
269 //
270 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
|
271 kumpf 1.3 "Duplicate user: $0.", userName);
|
272 mike 1.2 }
273 }
274
275 ifs.close();
|
276 kumpf 1.7 PEG_METHOD_EXIT();
|
277 mike 1.2 }
278
279
280 /**
281 Save the username and password to the password file.
282 */
283 void PasswordFile::save (PasswordTable& passwordTable)
284 {
|
285 kumpf 1.7 PEG_METHOD_ENTER(TRC_USER_MANAGER, "PasswordFile::save");
|
286 mike 1.2
287 //
|
288 kumpf 1.3 // Check if backup password file exists, if it does remove the password file
289 // If it does not rename the password file to password backup file
|
290 mike 1.2 //
291 if (FileSystem::exists(_passwordBackupFile))
292 {
|
293 kumpf 1.3 if ( FileSystem::exists(_passwordFile))
|
294 mike 1.2 {
|
295 kumpf 1.3 if ( ! FileSystem::removeFile(_passwordFile))
296 {
297 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::SEVERE,
298 "Cannot remove password file : $0.", _passwordFile);
299 throw CannotRemoveFile(_passwordFile);
300 }
|
301 mike 1.2 }
302 }
|
303 kumpf 1.3 else
|
304 mike 1.2 {
|
305 kumpf 1.3 if ( FileSystem::exists(_passwordFile))
|
306 mike 1.2 {
|
307 kumpf 1.3 if ( ! FileSystem::renameFile(_passwordFile, _passwordBackupFile))
308 {
309 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::SEVERE,
310 "Cannot rename password file : $0.", _passwordFile);
311 throw CannotRenameFile(_passwordFile);
312 }
|
313 mike 1.2 }
314 }
315
316 //
|
317 kumpf 1.3 // Open the password file for writing
|
318 mike 1.2 //
|
319 kumpf 1.3 ArrayDestroyer<char> p(_passwordFile.allocateCString());
|
320 mike 1.2 ofstream ofs(p.getPointer());
321 if (!ofs)
322 {
|
323 kumpf 1.7 PEG_METHOD_EXIT();
|
324 mike 1.2 throw CannotOpenFile(getFileName());
325 }
326
327 ofs.clear();
328
329 //
330 // Write password file header information
331 //
332
333 for (int index = 0; index < HEADER_SIZE; index++)
334 {
335 ofs << PasswordFileHeader[index] << endl;
336 }
337
338 ofs << endl;
339
340 //
341 // Save user names and passwords to the new file
342 //
343 for (PasswordTable::Iterator i = passwordTable.start(); i; i++)
344 {
345 mike 1.2 ofs << i.key() << ":" << i.value() << endl;
346 }
347
348 ofs.close();
349
|
350 kumpf 1.3 if ( FileSystem::exists(_passwordBackupFile))
|
351 mike 1.2 {
|
352 kumpf 1.3 if ( ! FileSystem::removeFile(_passwordBackupFile))
|
353 mike 1.2 {
|
354 kumpf 1.3 Logger::put(Logger::ERROR_LOG, "CIMPassword",
355 Logger::SEVERE,
356 "Cannot remove backup password file : $0.",
357 _passwordBackupFile);
358 throw CannotRemoveFile(_passwordBackupFile);
|
359 mike 1.2 }
360 }
|
361 kumpf 1.7 PEG_METHOD_EXIT();
|
362 mike 1.2 }
363
364 PEGASUS_NAMESPACE_END
365
|