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 _passwordNewFile = fileName + ".new";
100
101 // ATTN: Temporary hack to work when the password file is absent
102 if (!FileSystem::exists(_passwordFile))
103 {
104 PasswordTable pt;
105 save(pt);
106 mike 1.2 }
107
108 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
109 }
110
111 /**
112 Destructor.
113 */
114 PasswordFile::~PasswordFile ()
115 {
116 const char METHOD_NAME[] = "PasswordFile::~PasswordFile";
117 PEG_FUNC_ENTER(TRC_USER_MANAGER,METHOD_NAME);
118
119 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
120 }
121
122 /**
123 Load the username and password from the password file.
124 */
125 void PasswordFile::load (PasswordTable& passwordTable)
126 {
127 mike 1.2 String line;
128 const char METHOD_NAME[] = "PasswordFile::load";
129
130 PEG_FUNC_ENTER(TRC_USER_MANAGER,METHOD_NAME);
131
132 //
133 // Open the password file
134 //
135 ArrayDestroyer<char> p(_passwordFile.allocateCString());
136 ifstream ifs(p.getPointer());
137 if (!ifs)
138 {
139 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
140 throw CannotOpenFile(getFileName());
141 }
142
143 //
144 // Read each line of the file
145 //
146 for (Uint32 lineNumber = 1; GetLine(ifs, line); lineNumber++)
147 {
148 mike 1.2 // Get the userName and password
149
150 //
151 // Skip leading whitespace
152 //
153 const Char16* p = line.getData();
154
155 while (*p && isspace(*p))
156 {
157 p++;
158 }
159
160 if (!*p)
161 {
162 continue;
163 }
164
165 //
166 // Skip comment lines
167 //
168 if (*p == '#')
169 mike 1.2 {
170 continue;
171 }
172
173 //
174 // Get the userName
175 //
176 String userName = String::EMPTY;
177
178 userName += *p++;
179
180 while (isalnum(*p))
181 {
182 userName += *p++;
183 }
184
185 //
186 // Skip whitespace after user name
187 //
188 while (*p && isspace(*p))
189 {
190 mike 1.2 p++;
191 }
192
193 //
194 // Expect a colon sign
195 //
196 if (*p != COLON)
197 {
198 //
199 // Did not find Colon, log a message and skip entry
200 //
201 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
202 "Error in reading password entry for : $0, .", userName);
203 continue;
204 }
205
206 p++;
207
208 //
209 // Skip whitespace after : sign
210 //
211 mike 1.2 while (*p && isspace(*p))
212 {
213 p++;
214 }
215
216 //
217 // Get the password
218 //
219 String password = String::EMPTY;
220
221 while (*p)
222 {
223 password += *p++;
224 }
225
226 //
227 // Store the user name and password in the table
228 //
229 if (!passwordTable.insert(userName, password))
230 {
231 //
232 mike 1.2 // Duplicate entry for user, ignore the new entry.
233 //
234 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
235 "Duplicate user: $0, .", userName);
236 }
237 }
238
239 ifs.close();
240 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
241 }
242
243
244 /**
245 Save the username and password to the password file.
246 */
247 void PasswordFile::save (PasswordTable& passwordTable)
248 {
249 const char METHOD_NAME[] = "PasswordFile::save";
250
251 PEG_FUNC_ENTER(TRC_USER_MANAGER, METHOD_NAME);
252
253 mike 1.2 //
254 // Delete the backup password file
255 //
256 if (FileSystem::exists(_passwordBackupFile))
257 {
258 if ( ! FileSystem::removeFile(_passwordBackupFile))
259 {
260 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
261 "Cannot remove backup password file : $0, .", _passwordBackupFile);
262 }
263 }
264
265 //
266 // Delete the new password file
267 //
268 if (FileSystem::exists(_passwordNewFile))
269 {
270 if ( ! FileSystem::removeFile(_passwordNewFile))
271 {
272 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
273 "Cannot remove new password file : $0, .", _passwordNewFile);
274 mike 1.2 }
275 }
276
277 //
278 // Open the new password file for writing
279 //
280 ArrayDestroyer<char> p(_passwordNewFile.allocateCString());
281 ofstream ofs(p.getPointer());
282 if (!ofs)
283 {
284 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
285 throw CannotOpenFile(getFileName());
286 }
287
288 ofs.clear();
289
290 //
291 // Write password file header information
292 //
293
294 for (int index = 0; index < HEADER_SIZE; index++)
295 mike 1.2 {
296 ofs << PasswordFileHeader[index] << endl;
297 }
298
299 ofs << endl;
300
301 //
302 // Save user names and passwords to the new file
303 //
304 for (PasswordTable::Iterator i = passwordTable.start(); i; i++)
305 {
306 ofs << i.key() << ":" << i.value() << endl;
307 }
308
309 ofs.close();
310
311 //
312 // Rename the current password file as the backup file
313 //
314 if (FileSystem::exists(_passwordFile))
315 {
316 mike 1.2 if (!FileSystem::renameFile(_passwordFile, _passwordBackupFile))
317 {
318 throw CannotRenameFile(_passwordFile);
319 }
320 }
321
322 //
323 // Rename the new password file as the password file
324 //
325 if (FileSystem::exists(_passwordNewFile))
326 {
327 if (!FileSystem::renameFile(_passwordNewFile, _passwordFile))
328 {
329 FileSystem::renameFile(_passwordBackupFile, _passwordFile);
330 throw CannotRenameFile(_passwordNewFile);
331 }
332 if ( ! FileSystem::removeFile(_passwordBackupFile))
333 {
334 Logger::put(Logger::ERROR_LOG, "CIMPassword", Logger::INFORMATION,
335 "Cannot remove backup password file : $0, .", _passwordBackupFile);
336 }
337 mike 1.2 }
338 PEG_FUNC_EXIT(TRC_USER_MANAGER,METHOD_NAME);
339 }
340
341 PEGASUS_NAMESPACE_END
342
|