1 karl 1.14 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.7 // 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.4 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.7 // 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.8 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.14 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.2 //
|
14 kumpf 1.3 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // 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 // 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 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // 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 // 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 // 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 mike 1.2 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include "LocalAuthFile.h"
35
|
36 tony 1.5 #include <fstream>
37 #ifndef PEGASUS_OS_TYPE_WINDOWS
38 #include <unistd.h>
39 #endif
40 #include <errno.h>
41 #include <sys/stat.h>
42 #include <sys/types.h>
43 #ifndef PEGASUS_OS_TYPE_WINDOWS
44 #include <sys/time.h>
45 #endif
46
47 #include <Pegasus/Common/System.h>
48 #include <Pegasus/Common/FileSystem.h>
49 #include <Pegasus/Common/Tracer.h>
|
50 mike 1.18 #include <Pegasus/Common/Mutex.h>
|
51 tony 1.5 #include <Pegasus/Config/ConfigManager.h>
52 #if defined(PEGASUS_OS_OS400)
53 #include "OS400ConvertChar.h"
54 #endif
55
56 #include "LocalAuthFile.h"
57
58 #if defined(PEGASUS_OS_OS400) || defined(PEGASUS_OS_TYPE_WINDOWS)
59 // srandom( ) and random( ) are srand( ) and rand( ) on OS/400 and windows
60 #define srandom(x) srand(x)
61 #define random() rand()
62 #endif
63
64
65 PEGASUS_USING_STD;
66
67 PEGASUS_NAMESPACE_BEGIN
68
69 //
70 // Constant representing the random seed for srandom function
71 //
72 tony 1.5 const Uint32 RANDOM_SEED = 100;
73
74 //
75 // File path used to create temporary random file
76 //
77 const char TMP_AUTH_FILE_NAME [] = "/cimclient_";
78
79 //
80 // Constant representing the int buffer size
81 //
82 const Uint32 INT_BUFFER_SIZE = 16;
83
84 //
85 // Constant representing the random device name
86 //
87 const char DEV_URANDOM [] = "/dev/urandom";
88
89 //
90 // Constant representing the size of random entropy needed
91 //
92 const Uint32 RANDOM_BYTES_NEEDED = 20; // require minimum 160 bits = 20 bytes of randomness
93 tony 1.5
94 //
95 // A unique sequence number used in random file name creation.
96 //
97 static Uint32 sequenceCount = 1;
98 static Mutex sequenceCountLock;
99
100
101
102 LocalAuthFile::LocalAuthFile(const String& userName)
|
103 sushma.fernandes 1.23 : _userName(userName)
|
104 tony 1.5 {
105 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::LocalAuthFile()");
106
107 srandom(RANDOM_SEED);
108
109 //
110 // get the configured temporary authentication file path
111 //
|
112 h.sterling 1.12 _authFilePath = PEGASUS_LOCAL_AUTH_DIR;
|
113 tony 1.5
|
114 mike 1.2 #if defined(PEGASUS_OS_TYPE_WINDOWS)
|
115 tony 1.5 System::makeDirectory((const char *)_authFilePath.getCString());
116 #endif
117 _authFilePath.append(TMP_AUTH_FILE_NAME);
118
119 PEG_METHOD_EXIT();
120 }
121
122 LocalAuthFile::~LocalAuthFile()
123 {
124 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::~LocalAuthFile()");
125
126 PEG_METHOD_EXIT();
127 }
128
129 //
130 // create a file and make a random token data entry to it.
131 // send the file name back to caller
132 //
133 String LocalAuthFile::create()
134 {
135 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::create()");
136 tony 1.5
137 Uint32 secs, milliSecs;
138 Uint32 mySequenceNumber;
139
140 System::getCurrentTime(secs, milliSecs);
141
142 //
143 // extension size is username plus the sequence count
144 //
|
145 a.arora 1.6 {
146 AutoMutex autoMut(sequenceCountLock);
147 mySequenceNumber = sequenceCount++;
148 } // mutex unlocks here
|
149 tony 1.5
150 char extension[2*INT_BUFFER_SIZE];
151 sprintf(extension,"_%u_%u", mySequenceNumber, milliSecs);
152 extension[strlen(extension)] = 0;
153
|
154 sushma.fernandes 1.23 String filePath;
|
155 tony 1.5
|
156 h.sterling 1.10 //Check to see whether a domain was specified. If so, strip the domain from the
157 //local auth file name, since the backslash and '@' are invalid filename characters.
158 //Store this in another variable, since we need to keep the domain around for
159 //the rest of the operations. Bug 3076
160 String fileUserName = _userName;
161 Uint32 index = _userName.find('\\');
162 if (index != PEG_NOT_FOUND)
163 {
164 fileUserName = _userName.subString(index + 1);
165
166 } else
167 {
168 index = _userName.find('@');
169 if (index != PEG_NOT_FOUND)
170 {
171 fileUserName = _userName.subString(0, index);
172 }
173 }
174
|
175 tony 1.5 filePath.append(_authFilePath);
|
176 h.sterling 1.10 filePath.append(fileUserName);//_userName);
|
177 tony 1.5 filePath.append(extension);
178 CString filePathCString = filePath.getCString();
179
180 //
181 // 1. Create a file name for authentication.
182 //
183 #if defined(PEGASUS_OS_OS400)
184 ofstream outfs(filePathCString, PEGASUS_STD(_CCSID_T(1208)));
185 #else
186 ofstream outfs(filePathCString);
187 #endif
188 if (!outfs)
189 {
190 // unable to create file
191 PEG_TRACE_STRING(TRC_AUTHENTICATION, Tracer::LEVEL4,
192 "Failed to create local auth file: " +
193 filePath + ", " + strerror(errno));
|
194 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
195 thilo.boehm 1.19 "Security.Authentication.LocalAuthFile.NO_CREATE",
196 "Creation of the local authentication security file"
197 " $0 failed: $1",filePath,strerror(errno));
|
198 tony 1.5 PEG_METHOD_EXIT();
199 throw CannotOpenFile (filePath);
200 }
201 outfs.clear();
202
203 //
|
204 thilo.boehm 1.13 // 2. Set file permission to read/write by the owner only.
|
205 tony 1.5 //
|
206 dave.sudlik 1.15
207 #if defined(PEGASUS_OS_TYPE_WINDOWS)
208 Boolean success =
209 FileSystem::changeFilePermissions(filePath, _S_IREAD | _S_IWRITE);
210 #else
211 Boolean success =
212 FileSystem::changeFilePermissions(filePath, S_IRUSR | S_IWUSR);
213 #endif
|
214 thilo.boehm 1.13
|
215 dave.sudlik 1.15 if ( !success )
|
216 tony 1.5 {
217 String errorMsg = strerror(errno);
218 PEG_TRACE_STRING(TRC_AUTHENTICATION, Tracer::LEVEL4,
219 "Failed to change mode on file: " + filePath
220 + ", err is: " + errorMsg);
221 PEG_METHOD_EXIT();
222
223 // Unable to change the local auth file permissions, remove the file
224 // and throw CannotOpenFile error.
|
225 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
226 thilo.boehm 1.19 "Security.Authentication.LocalAuthFile.NO_CHMOD",
227 "Changing permissions of the local authentication security file"
228 " $0 failed: $1",filePath,strerror(errno));
|
229 tony 1.5
230 if (filePath.size())
231 {
232 if (FileSystem::exists(filePath))
233 {
234 FileSystem::removeFile(filePath);
235 }
236 }
237
|
238 thilo.boehm 1.19 PEG_METHOD_EXIT();
|
239 tony 1.5 throw CannotOpenFile (filePath);
240 }
241
242 //
243 // 3. Generate random token and write the token to the file.
244 //
245 String randomToken = _generateRandomTokenString();
246 outfs << randomToken;
|
247 thilo.boehm 1.19
248 // test if the write was successful
249 if (outfs.fail())
250 {
251 PEG_TRACE_STRING(TRC_AUTHENTICATION, Tracer::LEVEL4,
252 "Failed to write security token to file: "
253 + filePath );
254
|
255 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
256 thilo.boehm 1.19 "Security.Authentication.LocalAuthFile.NO_WRITE",
257 "Cannot write security token to the local authentication"
258 " security file $0.",filePath);
259
260 if (filePath.size())
261 {
262 if (FileSystem::exists(filePath))
263 {
264 FileSystem::removeFile(filePath);
265 }
266 }
267
268 PEG_METHOD_EXIT();
269 throw CannotOpenFile (filePath);
270
271 }
272
|
273 tony 1.5 outfs.close();
274
275 //
|
276 thilo.boehm 1.13 // 4. Set file permission to read only by the owner.
277 //
|
278 dave.sudlik 1.15 #if defined(PEGASUS_OS_TYPE_WINDOWS)
279 success =
280 FileSystem::changeFilePermissions(filePath, _S_IREAD);
281 #else
282 success =
283 FileSystem::changeFilePermissions(filePath, S_IRUSR);
284 #endif
|
285 thilo.boehm 1.13
|
286 dave.sudlik 1.15 if ( !success )
|
287 thilo.boehm 1.13 {
288 String errorMsg = strerror(errno);
289 PEG_TRACE_STRING(TRC_AUTHENTICATION, Tracer::LEVEL4,
290 "Failed to change mode on file: " + filePath
291 + ", err is: " + errorMsg);
292 PEG_METHOD_EXIT();
293
294 // Unable to change the local auth file permissions, remove the file
295 // and throw CannotOpenFile error.
|
296 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
297 thilo.boehm 1.19 "Security.Authentication.LocalAuthFile.NO_CHMOD",
298 "Changing permissions of the local authentication security file"
299 " $0 failed: $1",filePath,strerror(errno));
|
300 thilo.boehm 1.13
301 if (filePath.size())
302 {
303 if (FileSystem::exists(filePath))
304 {
305 FileSystem::removeFile(filePath);
306 }
307 }
308
|
309 thilo.boehm 1.19 PEG_METHOD_EXIT();
|
310 thilo.boehm 1.13 throw CannotOpenFile (filePath);
311 }
312
313 //
314 // 5. Change the file owner to the requesting user.
|
315 tony 1.5 //
|
316 msolomon 1.20
317 if (!FileSystem::changeFileOwner(filePath,_userName))
|
318 tony 1.5 {
319 String errorMsg = strerror(errno);
320 PEG_TRACE_STRING(TRC_AUTHENTICATION, Tracer::LEVEL4,
321 "Failed to change owner of file '" + filePath + "' to '" +
322 _userName + "', err is: " + errorMsg);
323 PEG_METHOD_EXIT();
324
325 // Unable to change owner on local auth file, remove the file
326 // and throw CannotOpenFile error.
327
|
328 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
329 thilo.boehm 1.19 "Security.Authentication.LocalAuthFile.NO_CHOWN_REQUSER",
330 "Changing ownership of the local authentication"
331 " security file $0 to the requesting user failed: $1"
332 ,filePath,strerror(errno));
333
|
334 tony 1.5 if (filePath.size())
335 {
336 if (FileSystem::exists(filePath))
337 {
338 FileSystem::removeFile(filePath);
339 }
340 }
341
|
342 thilo.boehm 1.19 PEG_METHOD_EXIT();
|
343 tony 1.5 throw CannotOpenFile (filePath);
344 }
345
|
346 sushma.fernandes 1.23 _secret = randomToken;
|
347 tony 1.5
348 _filePathName = filePath;
349
350 PEG_METHOD_EXIT();
351
352 return(_filePathName);
353 }
354
355 //
356 // Removes the file that was created
357 //
358 Boolean LocalAuthFile::remove()
359 {
360 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::remove()");
361
362 Boolean retVal = true;
363
364 //
365 // remove the file
366 //
367 if (FileSystem::exists(_filePathName))
368 tony 1.5 {
|
369 marek 1.16
|
370 a.dunfey 1.22 #if !defined(PEGASUS_OS_TYPE_WINDOWS)
|
371 a.dunfey 1.17 // change ownership back to the CIMOM
|
372 marek 1.16 #if defined(PEGASUS_OS_OS400)
373 CString tempPath = _filePathName.getCString();
374 const char * tmp1 = tempPath;
375 AtoE((char *)tmp1);
376 int rc = chown(tmp1, geteuid(), getegid());
377 #else
378 int rc = chown((const char *)_filePathName.getCString(), geteuid(), getegid());
379 #endif
380 if(rc == -1 )
381 {
|
382 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::WARNING,
|
383 marek 1.16 "Security.Authentication.LocalAuthFile.NO_CHOWN",
384 "Changing ownership of the local authentication"
385 " security file back to the CIMServer UserId failed.");
386 }
|
387 a.dunfey 1.17 #endif
|
388 marek 1.16
|
389 tony 1.5 retVal = FileSystem::removeFile(_filePathName);
390 }
391
392 PEG_METHOD_EXIT();
393
394 return(retVal);
395 }
396
397 //
|
398 sushma.fernandes 1.23 // Get the string that was created as a secret string
|
399 tony 1.5 //
|
400 sushma.fernandes 1.23 String LocalAuthFile::getSecretString()
|
401 tony 1.5 {
|
402 sushma.fernandes 1.23 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::getSecretString()");
|
403 tony 1.5
404 PEG_METHOD_EXIT();
405
|
406 sushma.fernandes 1.23 return(_secret);
|
407 tony 1.5 }
408
409
410 //
411 // Generate random token string
412 //
413 String LocalAuthFile::_generateRandomTokenString()
414 {
415 PEG_METHOD_ENTER(TRC_AUTHENTICATION,
416 "LocalAuthFile::_generateRandomTokenString()");
417
|
418 sushma.fernandes 1.23 String randomToken;
|
419 tony 1.5
420 String randFile = String(DEV_URANDOM);
421 FILE *fh;
422
423 //
424 // If /dev/urandom exists then read random token from /dev/urandom
425 //
426 if ( ( fh = fopen( (const char *)randFile.getCString(), "r") ) != NULL )
427 {
428 char token[RANDOM_BYTES_NEEDED+1];
429
430 setvbuf(fh, NULL, _IONBF, 0); // need unbuffered input
|
431 a.dunfey 1.22 Uint32 n = (Uint32)fread( (unsigned char *)token, 1,
432 RANDOM_BYTES_NEEDED, fh );
|
433 tony 1.5 fclose(fh);
434 token[n]=0;
435
436 randomToken.clear();
437 char hexChar[10];
438
439 for (Uint32 i=0; i < n; i++)
440 {
441 sprintf(hexChar, "%X", (unsigned char)token[i]);
442 randomToken.append(String(hexChar));
443 memset(hexChar, 0x00, sizeof(hexChar));
444 }
445 }
446
447 char token[2*INT_BUFFER_SIZE];
448 Uint32 seconds, milliseconds;
449
450 System::getCurrentTime(seconds, milliseconds);
451
452 //
453 // generate a random token
454 tony 1.5 //
455 char randnum[] = { '0' + (random() % 10), '0' + (random() % 10), '\0' };
456 long randomNum = atol(randnum);
457
458 sprintf (token,"%ld%d", randomNum, seconds + milliseconds );
459 token[strlen(token)] = 0;
460
461 randomToken.append(_userName);
462 randomToken.append(token);
463
464 PEG_METHOD_EXIT();
465
466 return (randomToken);
467 }
468
469 PEGASUS_NAMESPACE_END
|